Re:Scala 3.0.0-M1
by valenterry on Wednesday November 04, 2020 @06:48AM
(#24988195)
Ah, I understand what you mean now. You are looking indeed for the thrush operator. I think it should be built into Scala's standard library, but until that happens, you can use the mouse library or build it yourself. Here is an example:
// Need to define this once somewhere in your project
implicit class TrushExtension[A](anything: A) {
def |>[B](function: A => B) = function(anything)
}
// Your application code
def fun(arr: Iterable[Int]) = arr.map(_.toDouble / Math.PI)
val arr = 0 to 100
val newArr = arr.map(_*2) |> fun
newArr.foreach(println) // prints 0, 0.63662, 1.27324, ...
Execute or change the code here: https://scalafiddle.io/sf/WAKhZtJ/0This is maybe not exactly as convenient, but it comes pretty close.
"someA.someB.someC" becomes "someA |> someB |> someC".
If you would call it pipe operator, like it's called in many (Elm, Elixir, F#, OCaml) other languages that have it, people would understand you faster IMHO. It is even discussed for inclusion into JavaScript.
Re:Scala 3.0.0-M1
by valenterry on Wednesday November 04, 2020 @09:35AM
(#24989371)
Nice I didn't know that! I still like to add |> on top of it.
"foo |> bar |> baz" just visually parses easier than "foo pipe bar pipe baz"
Re:Scala 3.0.0-M1
by tastyminerals2 on Wednesday November 04, 2020 @06:52AM
(#24988212)
Looks good! Thanks for the tip.
Scala is more strict than D for this use case. In Scala, if you want a function to be available to a certain type as if it was a method call, you need to be explicit about it. You have to declare an "implicit class" that takes the base type as an argument, and define the function as a method of the implicit class. You also need to ensure the implicit class is in scope. Once these conditions are met, you can use it as a method.
val t1 = MyType()
def fun(t: MyType, argument: Int) = argument
// can't do this yet
// t1.fun(42)
// In Scala 2 you use an implicit class to add methods to a type
implicit class MyEnrichedType(t: MyType) {
def fun(argument: Int) = fun(t, argument)
}
// In Scala 3 you use an extension
extension (t: MyType)
def fun(argument: Int) = fun(t, argument)
// now it can be done
t.fun(42)
Regarding your question about the stdlib methods being able to be chained: they are not special. They are defined for the type the methods return, so they can be used.Rejecting all kinds of implicits and then complaining about Scala missing features is a bit unfair. "Implicit"is a single keyword, but not a single feature. Implicit arguments, implicit conversions and implicit classes are not the same thing. Fortunately, Scala 3 will clear this misunderstanding.
This was just an example. It's not about filter at all but the general method chaining.
Here is example from D if I must:
I don't know how you can chain a custom method "fun" to the output of the "map" in Scala without duck typing. Why is this not possible when all conditions type-wise are met? Why you can chain std methods like map, filter, reduce, fold etc. but not custom ones?