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