Scala reminder: Gotta name an argument to use it twice
This is going to be a short article. Scala is a very powerful programming language with a generally concise syntax. Trouble is, every so often I forget certain details of that concise syntax. Like, for example, how do you use a wildcard twice?
I learned quickly enough how to use a wildcard once. For example:
scala> LazyList.iterate(1: BigInt)(_ * 7)
res0: scala.collection.immutable.LazyList[BigInt] = LazyList(<not computed>)
The first pair of parentheses enclose 1 as a BigInt
. In the second pair of parentheses, the underscore wildcard represents, on the first iteration, the initial value (1, in the example), and on later iterations the value computed by the previous iteration.
So the value represented by the wildcard is, in the example, multiplied by the integer 7. Thanks to an implicit conversion I generally take for granted, the Int
is converted to a BigInt
, and thanks to “operator overloading,” we can use the multiplication operator instead of multiply()
or times()
or whatever it might otherwise be called.
Thus the first iteration produces 7, then the second iteration gives 49, and so on and so forth.
scala> res0.take(20).toList
res1: List[BigInt] = List(1, 7, 49, 343, 2401, 16807, 117649, 823543, 5764801, 40353607, 282475249, 1977326743, 13841287201, 96889010407, 678223072849, 4747561509943, 33232930569601, 232630513987207, 1628413597910449, 11398895185373143)
Copy and paste to the OEIS search box, the very first result should be A420, the powers of 7. In fact it should be the only result.
Sometimes though, you need to use the wildcard twice.
For example, consider the method to approximate square roots that is sometimes attributed to Sir Isaac Newton. By “Newton’s method,” we approximate the square root of x by starting with an initial guess g(0), which we progressively refine by the formula g(n) = (g(n − 1) + x/g(n − 1))/2.
Here g(n − 1) seems like a perfect choice for a LazyList
iteration that uses the wildcard twice in the iterated function. Except that you can’t do that in Scala. There are Scala expressions in which you can use two underscore wildcards, but this is not one of those.
scala> def newtonSqrt(x: Double, initGuess: Double): LazyList[Double] = LazyList.iterate(initGuess)((_ + x/_)/2)
^
error: missing parameter type for expanded function ((<x$1: error>, x$2) => x$1.$plus(x.$div(x$2)))
^
error: missing parameter type for expanded function ((<x$1: error>, <x$2: error>) => x$1.$plus(x.$div(x$2)))
So I have to give the underscore wildcard a type? That doesn’t sound right.
After some searching with Google, I came across the Scala cheat sheet by Brendan O’Connor.
(1 to 5).map(x => x * x)
Anonymous function: to use an [argument] twice, [you] have to name it.
A-ha! I have to name the “wildcard,” but I don’t have to specify its type, that’s inferred by the compiler.
scala> def newtonSqrt(x: Double, initGuess: Double): LazyList[Double] = LazyList.iterate(initGuess)(g => (g + x/g)/2)
newtonSqrt: (x: Double, initGuess: Double)LazyList[Double]
Alright, that looks like it works. But the proof is in the pudding.
scala> newtonSqrt(13.0, 4.0)
res12: LazyList[Double] = LazyList(<not computed>)scala> res12.take(20).toList
res13: List[Double] = List(4.0, 3.625, 3.605603448275862, 3.6055512758414574, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896, 3.6055512754639896)scala> res13(19) * res13(19)
res14: Double = 13.000000000000002
For assertEquals()
in JUnit with type Double
(double
in Java), I generally use a delta of 0.00001. So 13.000000000000002 would be good enough with that delta.
Well, there you have it. In Scala, you can’t always use the underscore wildcard, but sometimes you can name a wildcard and use that twice.