In the various Lisps, it's possible for me to create a sequence of functions as if they'd just been normal values:
(def ops [+ - * /])
Which I can then iterate through, again, as if they were just normal values:
(doseq [op ops] // (doseq (op ops) is like for (op <- ops) in scala
(println (op 1 2 3 4)))
Now, I've tried a few things in Scala, all of them failing:
scala> List(+, -, *, /)
<console>:1: error: illegal start of simple expression
List(+, -, *, /)
^
scala> List[Double => Double](+, -, *, /)
<console>:1: error: illegal start of simple expression
List[Double => Double](+, -, *, /)
^
scala> List[Double => Double](+_, -_, *_, /_)
<console>:8: error: not found: value *
List[Double => Double](+_, -_, *_, /_)
^
<console>:8: error: not found: value /
List[Double => Double](+_, -_, *_, /_)
^
So what's the correct procedure of defining a list of functions/operators in Scala?
The problem is that these functions are binary operators, i.e., they take two operands and return one. So you have to use:
List[(Double, Double) => Double](_ + _, _ - _, _ * _, _ / _)
In Scala, most value-level operators are actually unary instance methods (maybe all are, not sure if there are counterexmaples). So when you talk about, say, addition of two values of type Double, you're really referring to a method of the first value that takes the second value as a parameter. The familiar infix operator syntax is just sugar. In other words,
scala> 5.7 + 6.3
res0: Double = 12.0
is really just a nice shorthand for:
scala> 5.7.+(6.3)
res1: Double = 12.0
As @bluenote10 already mentioned, you can capture these operators by creating anonymous function that take both the first instance and its operand as parameters and returns the result of the + method:
scala> (lhs: Double, rhs: Double) => lhs + rhs
res2: (Double, Double) => Double = <function2>
Or as in @bluenote10's example, if the type can be inferred (like in a list with the type provided), you can use the nice underscore syntax:
scala> val doublePlus: (Double, Double) => Double = _ + _
doublePlus: (Double, Double) => Double = <function2>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With