Understand syntactic sugar for lambda expressions - scala

I am struggling to understand the behavior of type inference. For example this fails to compile:
import math._
object Distance {
def euclidean (p: Seq[Double], c: Seq[Double]) = {
val d = (p,c)
.zipped map (_ - _)
.map pow(_,2.0)
.foldLeft(0.0)(_+_)
sqrt(d)
}
}
with:
Error:(5, 17) missing parameter type for expanded function ((x$3) =>
scala.Tuple2(p, c).zipped.map(((x$1, x$2) =>
x$1.$minus(x$2))).map.pow(scala.Tuple2(x$3, 2.0).foldLeft(0.0)(((x$4,
x$5) => x$4.$plus(x$5)))))
.map pow(_,2.0)
I somehow do not get how the de-sugaring works and I end up having to sprinkle around type declarations and parenthesis or getting rid of infix notations in favor of explicit method calls (with the .).
For example this one works:
import math._
object Distance {
def euclidean (p: Seq[Double], c: Seq[Double]) = {
val d = (p,c)
.zipped.map (_ - _)
.map ( (x:Double) => pow(x,2.0) )
.foldLeft(0.0)(_+_)
sqrt(d)
}
}
but no chance to have a cute oneliner:
(p,c).zipped map pow(_ - _, 2.0)
I'd be interested in understanding the rules of the game with a for dummies explanation.

The problem seems to be the infix notation. The rules are actually quite simple: A method taking one parameter can be written in an infix notation. So that you can write a b c instead of a.b(c).
It is however not that simple, because by omitting the explicit dots and parentheses, there must be something else deciding the priority of the operators. So that the compiler can decide that 1+2*3 is 1.+(2.*(3)) and not (1.+(2)).*(3). The precedence of the operators part of the specification you have linked and it is (simply said) governed by the leading symbol of the operator.
Another important detail to note is operators ending with a : bind the parameters from the right. So a :: b is equivalent to b.::(a).
Another tricky thing are the parentheses. In the dot notation they simply wrap the parameter lists. In the operator notation they might need to wrap the parameters themselves (e.g. the function literals).
Btw: Your one liner can be written like this: (p,c).zipped map {(a, b) => pow(a - b, 2.0)} Note that I've wrapped the function literal with {}, that is just for readability, () would work too.

Related

Scala - Make signature of function parameter f of higher order function g dependent on varars of g

I am trying to define a higher order function f which accepts a variable number of parameters args of type Wrapper[T]* and a function parameter g in Scala.
The function f should decapsulate each object passed in args and then call g with the decapsulated parameters. Therefore, g has to accept exactly the same number of parameters of type T as args contains.
The closest thing I could achieve was to pass a Seq[T] to g and to use pattern matching inside of g. Like the following:
f("This", "Is", "An", "Example")(x => x match {
case Seq(a:String, b:String, c:String): //Do something.
})
With f defined like:
def f[V](args: Wrapper[T]*)
(g: (Seq[T]) => (V)) : V = {
val params = args.map(x => x.unwrap())
g(params)
}
How is it possible to accomplish a thing like this without pattern
matching?
It is possible to omit the types in the signature of g
by using type inference, but only if the number of parameters is
fixed. How could this be done in this case?
It is possible to pass
different types of parameters into varargs, if a type wildcard is
used args: Wrapper[_]*. Additionally, casting the result of
x.unwrap to AnyRef and using pattern matching in g is
necessary. This, however, completely breaks type inference and type
safety. Is there a better way to make mixing types in the varargs
possible in this special case?
I am also considering the use of scala makros to accomplish these tasks.
Did I get you right? I replaced your Wrapper with some known type, but that doesn't seem to be essential.
def f[T, V](args: T*)(g: PartialFunction[Seq[T], V]): V = g(args)
So later you can do this:
f(1,2,3) { case Seq(a,b,c) => c } // Int = 3
Okay, I've made my own Wrapper to be totally clear:
case class Wrapper[T](val x:T) {
def unwrap = x
}
def f[V](args: Wrapper[_]*)(g: PartialFunction[Seq[_], V]): V =
g(args.map(_.unwrap))
f(Wrapper("1"), Wrapper(1), Wrapper(BigInt(1))) {
case Seq(s: String, i: Int, b: BigInt) => (s, i, b)
} // res3: (String, Int, BigInt) = (1,1,1)
Regarding your concerns about type safety and conversions: as you can see, there aren't any explicit conversions in the code above, and since you are going to pattern-match with explicitly defined types, you may not to worry about these things - if some items of an undefined origin are going to show in your input, scala.MatchError will be thrown.

Is <- only accessible by the compiler

Scala's <- arrow seems a bit strange. Most operators are implemented somewhere in the source as a function, defined on a data type, either directly or implicitly. <- on the other hand only seems to unusable outside of a for comprehension, where it acts as a syntactic element used to signal the binding of a new variable in a monadic context (via map).
This is the only instance I can think of where Scala has an operator-looking syntactical element that is only usable in a specific context, and isn't an actual function.
Am I wrong about how <- works? Is it a special case symbol used just by the compiler, or is there some way a developer could use this behavior when writing their own code?
For example, would it be possible to write a macro to transform
forRange (i <- 0 to 10) { print(i) }
into
{ var i = 0; while (i <= 10) { print(i) } }
instead of its standard map equivalent? As far as I can tell, any usage of i <- ... outside of a for context causes an exception due to referencing an unknown value.
In short, yes <- is a reserved operator in Scala. It's a compiler thing.
Foreach
There is a strong distinction between foreach and for yield, but the syntax is only syntactic sugar, transformed at compile time.
for (i <- 1 to 10) { statement } expression is translated to:
Range.from(1, 10).foreach(..)
Multiple variables:
for (i <- 1 to 10; y <- 2 to 100) {..} becomes:
Range.from(1, 10).foreach(
el => {Range.from(2, 100).foreach(..)});
With all the variations given by:
for (x <- someList) = someList.foreach(..).
Put simply, they all get de-sugared to foreach statements. The specific foreach being called is given by the collection used.
For yield
The for yield syntax is sugar for flatMap and map. The stay in the monad rule applies here.
for (x <- someList) yield {..} gets translated to a someList.flatMap(..).
Chained operations become hierarchical chains of map/flatMap combos:
for {
x <- someList; y <- SomeOtherList
} yield {} becomes:
someList.flatMap(x => {
y.flatMap(..)
}); and so on.
The point
The point is that the <- operator is nothing more than syntactic sugar to make code more readable, but it always gets replaced at compile time.
To emphasize Rob's point
Rob makes excellent examples of other Scala syntactic sugar.
A context bound
package somepackage;
class Test[T : Manifest] {}
Is actually translated to:
class Test[T](implicit evidence: Manifest[T])
As proof, try to alias a type with a context bound:
type TestAlias[T : Manifest] = somepackage.Test // error, the : syntax can't be used..
It is perhaps easy to see how the : Manifest part is actually not a type a parameter.
It's just easier to type class Test[T : Manifest] rather than class Test[T](implicit evidence: Manifest[T].
The <- operator is a reserved word in the language (see the Scala Language Specification, page 4), but it isn't alone. => is also a reserved word rather than a function. (Also _, :, =, <:, <%, >:, #, and #.) So you couldn't create a function with that name. I don't believe you could adapt it the way you're suggesting, either (though perhaps someone more clever will know a way). You could create a function called `<-` (with surrounding back-ticks), but that would probably be more awkward than it deserves.

Why does Scala require partial application of curried functions when assigning to a val?

In Scala, why is it that a curried function can easily be passed directly to other functions, but when assigning it to a val one needs to also partially apply it with _? For example, given the two functions:
def curried(a: Int)(b: Int) = a + b
def test(a: Int, f: Int => Int) = f(a)
I can easily pass curried to test with:
test(5, curried(5))
and everything is happy. However if I simply call curried(5) I get an error:
scala> curried(5)
<console>:9: error: missing arguments for method curried;
follow this method with `_' if you want to treat it as a partially applied function
curried(5)
If I change the call to include type information however, it works:
val 'curried: Int => Int = curried(5)
Can anyone explain the rational behind the inconsistency, surely the Scala compiler can infer that the function is Int => Int given the type definition on the original method?
The problem is not inferring the type, the problem is inferring your intent. Did you make a mistake, or did you intentionally curry the function?
Alas, the trailing underscore syntax is the formal syntax, and omitting it is syntactical sugar.
The underscore isn't always needed. From http://docs.scala-lang.org/cheatsheets/
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd
currying, obvious syntax.
def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd
currying, obvious syntax
def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd
currying, sugar syntax. but then:
val normer = zscore(7, 0.4) _
need trailing underscore to get the partial, only for the sugar version.

Scala - method call syntax

I am a beginning practitioner in Scala and I saw a few different syntax for calling a method. Some are nice, as ignoring parenthesis for a parameterless method, or ignoring the dot as in
1 to 10
but some really puzzle me. for instance:
breakable { ... }
this is simply a method call right? Can I also do that for more than one parameter or a parameter which is not a parameterless function?
Thanks
There are two standard ways of calling methods:
obj.method(params) // dot notation
obj method (params) // operator notation
The above can be modified in the following ways:
If params is a single parameter, you can replace () with {}.
If params is a single parameter and you are using operator notation, you can drop the parenthesis.
If method doesn't take parameters, you can drop (params) (that is, drop the empty ()).
If method ends with :, then it actually binds to the right in operator notation. That is, (params) method_: obj is equivalent to obj.method_:(params).
Either way, spaces are optional as long as identifiers can be told apart. So one can add spaces to the dot notation, like obj . method ( params ) or write .method(params) on the next line -- as often happens with call chaining --, as well as remove spaces from the operator notation, as in a+b.
There's also some stuff with tuple inference, but I try to avoid it, so I'm not sure of the exact rules.
None of these will explain the example you are confused about, however. Before I explain it, however, I'd like to show some syntactic sugars that can also be used to call methods:
obj(params) // equivalent to obj.apply(params)
obj.x = y // equivalent to obj.x_=(y), if obj.x also exists
obj(x) = y // equivalent to obj.update(x, y)
obj op= y // equivalent to obj = obj op y, if op is symbolic
~obj // equivalent to obj.unary_~; also for !, + and -, but no other symbol
Ok, now to the example you gave. One can import members of stable values. Java can do it for static methods with its static import, but Scala has a more general mechanism: importing from packages, objects or common instances is no different: it brings both type members and value members. Methods fall in the latter category.
So, imagine you have val a = 2, and you do import a._. That will bring into scope all of Int methods, so you can call them directly. You can't do +(2), because that would be interpreted as a call to unary_+, but you could call *(4), for example:
scala> val a = 2
a: Int = 2
scala> import a._
import a._
scala> *(4)
res16: Int = 8
Now, here's the rule. You can call
method(params)
If:
method was imported into scope.
You keep the parenthesis (even if there's only one parameter)
Note that there's a precedence issue as well. If you write obj method(params), Scala will presume method belongs to obj, even if it was imported into scope.
If we desugar this we will have:
breakable({ ... })
this matches signature
breakable: (op: ⇒ Unit): Unit
and uses so named call-by-name arguments (you may think of this as pass a block of code as argument)
More over scala allows you to write this:
scala> def foo (op1: => Unit)(op2: => Unit) = {op1;op2;}
foo: (op1: => Unit)(op2: => Unit)Unit
scala> foo { println(1) } { println(2) }
1
2
Above is the example of curried function

Scala partially applied curried functions

Why can't i rewrite
println(abc.foldRight(0)((a,b) => math.max(a.length,b)))
in
object Main {
def main(args : Array[String]) {
val abc = Array[String]("a","abc","erfgg","r")
println(abc.foldRight(0)((a,b) => math.max(a.length,b)))
}
}
to
println(abc.foldRight(0)(math.max(_.length,_)))
? scala interpreter yields
/path/to/Main.scala:4: error: wrong number of parameters; expected = 2
println(abc.foldRight(0)(math.max(_.length,_)))
^
one error found
Which is not descriptive enough for me. Isn't resulting lambda takes two parameters one of which being called for .length method, as in abc.map(_.length)?
abc.foldRight(0)(math.max(_.length, _)) will expand to something like abc.foldRight(0)(y => math.max(x => x.length, y)). The placeholder syntax expands in the nearest pair of closing parentheses, except when you have only the underscore in which case it will expand outside the closest pair of parentheses.
You can use abc.foldRight(0)(_.length max _) which doesn't suffer from this drawback.