I wrote the following simple program:
import java.util.{Set => JavaSet}
import java.util.Collections._
object Main extends App {
def test(set: JavaSet[String]) = ()
test(emptySet()) //fine
test(emptySet) //error
}
DEMO
And was really surprised the the final line test(emptySet) was not compiled. Why? What is the difference between test(emptySet())? I thought in Scala we could omit parenthesis freely in such cases.
See Method Conversions in Scala specification:
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 arguments are passed following the rules here.
Eta Expansion
Otherwise, if the method is not a constructor, and the expected type pt
is a function type (Ts′)⇒T′, eta-expansion 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().
The one you want is "Empty Application", but it's only applied if none of the earlier conversions are, and in this case "Eta Expansion" happens instead.
EDIT: This was wrong and #Jasper-M's comment is right. No eta-expansion is happening, "Empty Application" is just inapplicable to generic methods currently.
Related
Why call to method whose all parameters has default values is not the same than calling a method without parameter in scala?
Example:
scala> def a(a:Int=1)=print(a)
a: (a: Int)Unit
scala> def b=print(1)
b: Unit
scala> a
<console>:13: error: missing argument list for method a
Unapplied methods are only converted to functions when a function type
is expected.
You can make this conversion explicit by writing `a _` or `a(_)`
instead of `a`.
a
^
scala> b
1
However
scala>a()
1
works ok.
Shouldn't be the same call?
Scala enable Arity-0(a) method to omit parentheses.
https://docs.scala-lang.org/style/method-invocation.html#arity-0
I can think of at least one problem caused by not needing to write parenthesis. Consider the following:
val xs = List(1, 2, 3, 4)
def myFunc(x: Int = 42) = 2 * x
val ys = xs.map(myFunc)
Eta expansion is happening in my example, method is lifted into function. But if it was possible to invoke function with default parameters this way, syntax would be ambigous at least in this case. (I know that here invocation would lead to wrong argument type of map function, so in theory it is possible to resolve this ambiguity here, but it would mean that type of expression would have impact on the syntax interpretation, which is handled before type-checking in any language i know)
If you don't add a parenthesis after a, that will have several meanings.
a(): Unit
a(_): Int => Unit
Which one do you mean? Hence it force you to add parenthesis.
In Scala, a method can have zero or more parameter lists, each of which has zero or more parameters. If you want to call a method, you have to supply matching argument lists with matching arguments to the parameters and parameter lists.
In your case, you defined the method with one parameter list, ergo you need to call it with one argument list.
Shouldn't be the same call?
No, they are not the same. The first call has zero argument lists, the second call has one argument list. That's different.
There are some cases where Scala lets you call methods with a single empty parameter list by supplying no argument lists. The reason for this is simple convenience: you want to call Java getters (which are defined with an empty parameter list) the same way as Scala getters (which are defined without a parameter list). But, this doesn't work in general.
I looked at Scala Type Hierarchy
It's pretty clear that Unit is a subtype of AnyVal. So I tried this:
object Main extends App {
val u : Unit = Seq[String]()
}
and it compiled fine. But I expected some error. DEMO.
Why? Unit is not a supertype of a Seq
This happens because Unit can also be inferred from statements (in contrast with expressions). This means that if you use the Unit type annotation, the compiler will ignore the last value in your expression and return Unit after your actual code.
You can simply testing this, by casting your u back to its original type. You will get a cast error, because u isn't actually bound to your Seq.
Here's what happens if you run this in the REPL:
scala> u.asInstanceOf[Seq[String]]
java.lang.ClassCastException: scala.runtime.BoxedUnit cannot be cast to scala.collection.Seq
As Jasper-M correctly pointed out, the compiler will rewrite this to
val u: Unit = { Seq[String](); () }
Why? Unit is not a supertype of a Seq
You are assuming that the Seq is assigned to u. But it isn't:
println(u)
# ()
As you can see, the value of u is () (i.e. the unique singleton instance of Unit), not an empty Seq.
This is due to Value Discarding, which is described in clause 5 of section 6.26.1 Value Conversions of the Scala Language Specification:
The following seven implicit conversions can be applied to an expression e which has some value type T and which is type-checked with some expected type pt.
[…]
If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term { e; () }.
In plain English as opposed to "Speclish", what this means is: if you say "this is of type Unit", but it actually isn't, the compiler will return () for you.
The Unit type is sort-of the equivalent to a statement: statements have no value. Well, in Scala, everything has a value, but we have () which is a useless value, so what would in other languages be a statement which has no value, is in Scala an expression which has a useless value. And just like other languages which distinguish between expressions and statements have such things like statement expressions and expression statements (e.g. ECMAScript, Java, C, C++, C♯), Scala has Value Discarding, which is essentially its analog for an Expression Statement (i.e. a statement which contains an expression whose value is discarded).
For example, in C you are allowed to write
printf("Hello, World");
even though printf is a function which returns a size_t. But, C will happily allow you to use printf as a statement and simply discard the return value. Scala does the same.
Whether or not that's a good thing is a different question. Would it be better if C forced you to write
size_t ignoreme = printf("Hello, World");
or if Scala forced you to write
val _ = processKeyBinding(…)
// or
{ processKeyBinding(…); () }
instead of just
processKeyBinding(…)
I don't know. However, one of Scala's design goals is to integrate well with the host platform and that does not just mean high-performance language interoperability with other languages, it also means easy onboarding of existing developers, so there are some features in Scala that are not actually needed but exist for familiarity with developers from the host platform (e.g. Java, C♯, ECMAScript) – Value Discarding is one of them, while loops are another.
The following code doesn't compile:
def f[T](conv: Option[String => T]) {}
f(Some(_.toInt))
with <console>:13: error: missing parameter type for expanded function ((x$1) => x$1.toInt)
Of course, explicit type makes it fine:
scala> f(Some((x: String) => x.toInt))
Why the compiler can't infer String type here? Is there some kind of ambiguity?
In general, is it possible to check and examine manually the generated code from underscore expansion?
The basic problem (I believe) is that when typing Some(_.toInt), the compiler needs to infer the type parameter of Some.apply[A](x: A), and to do that, it first needs to typecheck the arguments. So _.toInt is typechecked with A (considered as an unknown type constant) as expected type. This fails, because anonymous functions are only allowed not to specify parameter types when the expected type is a function type (or starting with Scala 2.12, a Single Abstract Method type). Then the compiler tries again with undefined as the expected type, and fails for the same reason.
In this case, the expected return type would actually be sufficient to determine the type parameter, and then this would allow to typecheck _.toInt, but that's not how it is designed to work.
The gory details, if you want them, are in http://scala-lang.org/files/archive/spec/2.11/06-expressions.html, paragraphs 6.6, 6.23, and 6.26.4.
I am doing the Scala Coursera course, and lectures seem to be missing an explanation of how multiple parameter lists really work.
He makes claims like the averageDamp() function below could be called with just the first argument (f), allowing you to call it with the second later. It seems though that you need to do partial binding explicitly by following the call with "_".
However, if the partial binding call is being passed into another function that accepts a function with a signature matching the partially bound function, it will implicitly accept it, no "_" necessary.
Yet he doesn't use the term partial binding at all, just saying there is a special syntax in Scala for basically returning a closure, when in reality it is just partial binding. Or not?
scala> def averageDamp(f: Double => Double)(x: Double) = (x+f(x))/2
scala> def fixedPoint(f: Double => Double)(x: Int) = f(x)+1
scala> fixedPoint(averageDamp(x=>x+1))(2)
res29: Double = 3.5
scala> averageDamp(x=>x+1)
<console>:19: error: missing arguments for method averageDamp;
follow this method with `_' if you want to treat it as a partially applied function
averageDamp(x=>x+1)
A non-partial binding version of averageDamp might be like:
def averageDamp(f: Double => Double): (Double => Double) =
def inner(x: Double): Double =
(x+f(x))/2
inner
I guess my question is...is the multi-parameter list version of averageDamp() being passed into another function just implicit partial binding...or is this really some kind of special Scala syntax for returning an inner function/closure?
Yet he doesn't use the term partial binding at all, just saying there is a special syntax in Scala for basically returning a closure, when in reality it is just partial binding... is the multi-parameter list version of averageDamp() being passed into another function just implicit partial binding...or is this really some kind of special Scala syntax for returning an inner function/closure?
Why do you think it's one or the other? Supplying only some of parameter lists is a special syntax for partial application (not "binding", usually) of methods with multiple parameter lists.
I am new to Scala, and when I look at different projects, I see two styles for dealing with implicit arguments
scala]]>def sum[A](xs:List[A])(implicit m:Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
sum:[A](xs:List[A])(implicit m:Monoid[A])A
and
scala]]>def sum[A:Monoid](xs:List[A]): A ={
val m = implicitly[Monoid[A]]
xs.foldLeft(m.mzero)(m.mappend)
}
sum:[A](xs:List[A])(implicit evidence$1:Monoid[A])A
Based off the type of both functions, they match. Is there a difference between the two? Why would you want to use implicitly over implicit arguments? In this simple example, it feels more verbose.
When I run the above in the REPL with something that doesn't have an implicit, I get the following errors
with implicit param
<console>:11: error: could not find implicit value for parameter m: Monoid[String]
and
with implicitly and a: Monoid
<console>:11: error: could not find implicit value for evidence parameter of type Monoid[String]
In some circumstances, the implicit formal parameter is not directly used in the body of the method that takes it as an argument. Rather, it simply becomes an implicit val to be passed on to another method that requires an implicit parameter of the same (or a compatible) type. In that case, not having the overt implicit parameter list is convenient.
In other cases, the context bound notation, which is strictly syntactic sugar for an overt implicit parameter, is considered aesthetically desirable and even though the actual parameter is needed and hence the implicitly method must be used to get it is considered preferable.
Given that there is no semantic difference between the two, the choice is predicated on fairly subjective criteria.
Do whichever you like. Lastly note that changing from one to the other will not break any code nor would require recompilation (though I don't know if SBT is discriminting enough to forgo re-compiling code that can see the changed definition).