Why does line #2 below compile? It's (seemingly) not giving the required constructor arg.
class F(x: => Unit) {}
new F // Compiles (strange)
def f(x: =>Unit) = ()
f // Does not compile (good)
Is it permitted sugar just for this special case? Can you point to docs on the subject? I'm using Scala 2.9.0.
Scala Reference:
5.1.1 Constructor Invocations
If no explicit arguments are given, an
empty list () is implicitly supplied.
,where () stands for Unit
Related
I am following this tutorial and I see this code:
def totalCostWithDiscountFunctionParameter(donutType: String)(quantity: Int)(f: Double => Double): Double = {
println(s"Calculating total cost for $quantity $donutType")
val totalCost = 2.50 * quantity
println("inside totalCostWithDiscountFunctionParameter")
f(totalCost)
}
def applyDiscount(totalCost: Double): Double = {
val discount = 2 // assume you fetch discount from database
totalCost - discount
}
println(s"Total cost of 5 Glazed Donuts with discount function = ${totalCostWithDiscountFunctionParameter("Glazed Donut")(5)(applyDiscount(_))}")
What is the point of the _ in applyDiscount(_)? I can also remove it and just pass the function by name like this applyDiscount and the code works. What is the point of the underscore? Is it the same thing?
applyDiscount(_) is placeholder syntax for anonymous functions. This expands to:
x => applyDiscount(x)
When you pass the applyDiscount method to the function, i.e:
totalCostWithDiscountFunctionParameter("5")(applyDiscount)
Then scalac will perform eta-expansion, which means turning a method to a function value.
Do these have exactly the same semantics? Close, but not quite. Consider the following example given in What are all the uses of an underscore in Scala? (slightly modified, full credit to #Owen for the example and the provided answer)
trait PlaceholderExample {
def process[A](f: A => Unit)
val set: Set[_ => Unit]
set.foreach(process) // Error
set.foreach(process(_)) // No Error
}
The first errors at compile time while the second succeeds, why is that? Let's look at the code compiled with -Xprint:typer:
λ scalac -Xprint:typer Test.scala
FooBar.scala:11: error: polymorphic expression cannot be instantiated to expected type;
found : [A](A => Unit) => Unit
required: (Function1[_, Unit]) => ?
set.foreach(process) // Error
^
[[syntax trees at end of typer]]
package yuval.tests {
abstract trait PlaceholderExample extends scala.AnyRef {
def /*PlaceholderExample*/$init$(): Unit = {
()
};
def process[A](f: A => Unit): Unit;
<stable> <accessor> val set: Set[Function1[_, Unit]];
PlaceholderExample.this.set.foreach[U](process);
PlaceholderExample.this.set.foreach[Unit](((x$1: Function1[_, Unit]) => PlaceholderExample.this.process[_$1](x$1)))
}
}
First thing you see is a compilation error because scalac was unable to eta-expand the method process from a polymorphic method to a monomorphic function. Meaning, when scalac attempts to bind A to an actual type, it looks for a type (_ => Unit) => ? but fails because _ (an existential) is not a type.
On the other hand, the second example which is expanded to x => process(x) compiles because when scalac encounters a lambda expression with no explicit type annotation, it looks at the type of the method signature (in our case, foreach expects a _ => Unit, which is classified as a type) and successfully binds the type argument to process.
Thus, in most cases you'll find that the two are isomorphic (although they really aren't)(even IntelliJ recommended that I can write one instead of the other), but there are edge cases which does distinguish one from the other.
In the spec of scala 6.26.2, there are 4 kind of conversions for methods:
MethodConversions
The following four implicit conversions can be applied to methods which are not applied to some argument list.
Evaluation. A parameterless method m of type => T is always converted to type T by evaluating the expression to which m is bound.
Implicit Application. If the method takes only implicit parameters, implicit argu- ments are passed following the rules of §7.2.
Eta Expansion. Otherwise, if the method is not a constructor, and the expected type pt is a function type (Ts′) ⇒ T′, eta-expansion (§6.26.5) is performed on the expression e.
Empty Application. Otherwise, if e has method type ()T , it is implicitly applied to the empty argument list, yielding e().
Some scala code:
def hello(): String = "abc"
def world1(s: String) = s
def world2(s: => String) = s
def world3(s: () => String) = s
world1(hello)
world2(hello)
world3(hello)
My question is, for world1, world2 and world3, which conversion rule is applied to each of them?
def world1(s: String) = s
world1(hello)
Empty application: hello is evaluated as hello() and then passed as the argument of world1
def world2(s: => String) = s
world2(hello)
Eta-expansion + Evaluation: hello is expanded into a function and evaluated lazily.
def world3(s: () => String) = s
world3(hello)
Eta-expansion: hello is expanded to a Function0[String]
Eta-expansion is necessary because methods and functions are two different things, even though the scala compiler is very good at hiding this difference.
The difference comes from the fact that methods are a JVM concept, whereas first-class functions are a scala-specific concept.
You can try this out in a REPL. First, let's define a method hello
scala> def hello(s: String) = s"hello $s"
hello: (s: String)String
scala> hello.hashCode
<console>:9: error: missing arguments for method hello;
follow this method with `_' if you want to treat it as a partially applied function
hello.hashCode
^
Woops, hello is not a value (in the JVM sense)! Not having an hashcode is a proof of it.
Let's get a Function1 out of the hello method
scala> hello _
res10: String => String = <function1>
scala> (hello _).hashCode
res11: Int = 1710358635
A function is a value, so it has an hashcode.
What is the parameter "_" in below method call signify ?
Is this a wildcard that accepts a parameter of any type ?
val integerSorter = msort[Int]((a, b) => a < b) _
The method msort signature :
def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T] = {
The easiest way to explain this is probably to let the compiler do most of the explaining—just try the first line without the underscore:
scala> val integerSorter = msort[Int]((a, b) => a < b)
<console>:11: error: missing arguments for method msort;
follow this method with `_' if you want to treat it as a partially applied function
val integerSorter = msort[Int]((a, b) => a < b)
^
So there you have it—the msort method has two parameter lists, but you've only passed arguments for the first, and the trailing underscore is the syntax that Scala provides to tell the compiler that you want partial application in that situation.
(If you try that line in the REPL with the underscore, you'll see that the inferred type of integerSorter is List[Int] => List[Int], so to answer your second question, no, the underscore doesn't allow you to provide a parameter of any type.)
For more information, see section 6.7 of the language specification:
The expression e _ is well-formed if e is of method type or if e is a
call-by-name parameter. If e is a method with parameters, e _
represents e converted to a function type by eta expansion
(§6.26.5).
Reading the section on eta expansion may also be helpful.
msort takes two parameters, a function that returns a boolean, and a list of items to be sorted. the function integerSorter supplies the first parameter, and the underscore represents the list that still needs to be specified. look up currying (http://www.scala-lang.org/old/node/135.html) for a more detailed explanation.
I compile the following code
def foo(implicit x: Int, x2: Int) = println(x2 + x)
implicit val x : Int = 2
foo(1)
But the compiler moans about the number of arguments. Why would the above work if there was only parameter x marked as implicit, but it does not work in this example?
You have to put the implicit argument is a separated, its own parenthesis:
scala> def foo(x2: Int)(implicit x: Int) = println(x2 + x)
scala> implicit val x: Int 2
scala> foo(1)
3
If you put non implicit argument and implicit argument in the same parenthesis, you have to explicitly pass both arguments otherwise compiler will complain about the wrong number of arguments. Scala compiler will try to look for implicit arguments when it sees that the argument is marked as implicit and no argument has been passed explicitly. But compiler checks if the right number of argument has been passed before checking for the implicit.
This will work as you want:
def foo(x2: Int)(implicit x: Int) = println(x2 + x)
implicit val x : Int = 2
foo(1)
I'm not too deep into Scala internals and spec so I cannot give an in depth-explanation why this is, but you have to pass implicits with an extra set of parenthesis.
Edit:
Because I was curious I had a look around the interwebs. I will not retype all the stuff I just found myself so you can find more detailed information here: http://daily-scala.blogspot.de/2010/04/implicit-parameters.html
Implicit parameters are all-or-nothing. Either you pass all of them explicitly, or you don't pass any of them and the compiler picks implicits for all.
In the example you should you are passing a parameter to foo, so you have to pass everything. If you had only one parameter in foo, it would work because the number of parameters is correct (and the parameter would be passed explicitly). If you call foo without passing any parameters, it will also work because it will pick implicit val x for both parameters.
Given the following constructs for defining a function in Scala, can you explain what the difference is, and what the implications will be?
def foo = {}
vs.
def foo() = {}
Update
Thanks for the quick responses. These are great. The only question that remains for me is:
If I omit the parenthesis, is there still a way to pass the function around? This is what I get in the repl:
scala> def foo = {}
foo: Unit
scala> def baz() = {}
baz: ()Unit
scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit
scala> test(foo)
<console>:10: error: type mismatch;
found : Unit
required: () => Unit
test(foo)
^
scala> test(baz)
res1: () => Unit = <function0>
Update 2012-09-14
Here are some similar questions I noticed:
Difference between function with parentheses and without
Scala methods with no arguments
If you include the parentheses in the definition you can optionally omit them when you call the method. If you omit them in the definition you can't use them when you call the method.
scala> def foo() {}
foo: ()Unit
scala> def bar {}
bar: Unit
scala> foo
scala> bar()
<console>:12: error: Unit does not take parameters
bar()
^
Additionally, you can do something similar with your higher order functions:
scala> def baz(f: () => Unit) {}
baz: (f: () => Unit)Unit
scala> def bat(f: => Unit) {}
bat: (f: => Unit)Unit
scala> baz(foo)
scala> baz(bar)
<console>:13: error: type mismatch;
found : Unit
required: () => Unit
baz(bar)
^
scala> bat(foo)
scala> bat(bar) // both ok
Here baz will only take foo() and not bar. What use this is, I don't know. But it does show that the types are distinct.
Let me copy my answer I posted on a duplicated question:
A Scala 2.x method of 0-arity can be defined with or without parentheses (). This is used to signal the user that the method has some kind of side-effect (like printing out to std out or destroying data), as opposed to the one without, which can later be implemented as val.
See Programming in Scala:
Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state).
This convention supports the uniform access principle [...]
To summarize, it is encouraged style in Scala to define methods that take no parameters and have no side effects as parameterless methods, i.e., leaving off the empty parentheses. On the other hand, you should never define a method that has side-effects without parentheses, because then invocations of that method would look like a field selection.
Terminology
There are some confusing terminology around 0-arity methods, so I'll create a table here:
Programming in Scala
scala/scala jargon
def foo: Int
parameterless methods
nullary method
def foo(): Int
empty-paren methods
nilary method
I sounds cool to say "nullary method", but often people say it wrong and the readers will also be confused, so I suggest sticking with parameterless vs empty-paren methods, unless you're on a pull request where people are already using the jargons.
() is no longer optional in Scala 2.13 or 3.0
In The great () insert, Martin Odersky made change to Scala 3 to require () to call a method defined with (). This is documented in Scala 3 Migration Guide as:
Auto-application is the syntax of calling a nullary method without passing an empty argument list.
Note: Migration document gets the term wrong. It should read as:
Auto-application is the syntax of calling a empty-paren (or "nilary") method without passing an empty argument list.
Scala 2.13, followed Scala 3.x and deprecated the auto application of empty-paren methods in Eta-expand 0-arity method if expected type is Function0. A notable exception to this rule is Java-defined methods. We can continue to call Java methods such as toString without ().
To answer your second question, just add an _:
scala> def foo = println("foo!")
foo: Unit
scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit
scala> test(foo _)
res10: () => Unit = <function0>
scala> test(foo _)()
foo!
scala>
I would recommend always start definition with a function like:
def bar {}
and only in cases, when you are forced, to change it to:
def bar() {}
Reason: Let's consider these 2 functions from a point of possible usage. How they can be infoked AND where they can be passed.
I would not call this a function at all:
def bar {}
It can be invoked as:
bar
but not as a function:
bar()
We can use this bar when we define a higher-order function with a call-by-name parameter:
def bat(f: => Unit) {
f //you must not use (), it will fail f()
}
We should remember, that => Unit - is not even a function. You absolutely cannot work with a thunk as if it's a function insofar as you cannot choose to treat it as Function value to be stored or passed around. You can only trigger evaluations of the actual argument expression (any number of them).
Scala: passing function as block of code between curly braces
A function, defined with () has a bigger scope for usage. It can be used exactly, in the same context, as bar:
def foo() = {}
//invokation:
foo
//or as a function:
foo()
It can be passed into a function with a call-by-name parameter:
bat(foo)
Additionally, if we define a higher-order function, that accepts not a call-by-name pamameter, but a real function:
def baz(f: () => Unit) {}
We can also pass foo to the baz:
baz(foo)
As we can see standard functions like foo have a bigger scope for usage. But using a functions defined without () plus defining higher-order functions, that accept call-by-name parameter, let us use more clear syntax.
If you do not try to archive a better, more readable code, or if you need ability to pass your piece of code both to function defined with a call-by-name parameter and to a function defined with a real function, then define your function as standard one:
def foo() {}
If you prefer to write more clear and readable code, AND your function has no side-effects, define a function as:
def bar {}
PLUS try to define your higher-order function to accept a call-by-name parameter, but not a function.
Only when you are forced, only in this case use the previous option.