What is the type of `=> String` in scala?
There are several parameters in scala by name:
def hello(who: => String) = println("hello, " + who)
What type of parameter who
?
The scala REPL as function is displayed here:
hello: (who: => String)Unit
Is the type yet => String
? Is there a name for this? Or any kind of documentation for describing the type?
Other questions raised by answer
Question 1
(Upon reading the spec §3.3.1 (MethodTypes))
Method type is the type of the method, for example, I defined a method hello
:
def hello: String = "abc"
Its type can be written as:, => String
right? Although you can see the REPL response:
scala> def hello:String = "abc"
hello: String
If I define a method that has parameters:
def goodname(name: String): String = name + "!"
What type of method? It should look like String => String
but not. Because it is the type of the method and it String => String
is the type of the function.
Question 2
(Upon reading the spec §3.3.1 (MethodTypes))
I can understand this as:
def goodname(name: String): String = name + "!"
def print(f: String => String) = println(f("abc"))
print(goodname)
When I call print(goodname)
, the type goodname
will be converted to the type of the function String => String
, right?
But for a limitless method:
def hello: String = "abc"
What type of function can you convert? I tried:
def print(f: () => String) = println(f())
But this cannot be compiled:
print(hello)
Mistake:
error: type of mismatch; found: String required :() => String
Could you provide an example that works?
Question 3
(Upon reading the spec §6.26.2 (MethodConversions))
This conversion Evaluation occurs only when no type is applied to the argument. So for the code:
def myname:String = "abc"
def print(name: => String) = println(name)
print(myname)
My question is, when I call print(myname)
, is the conversion happening (I mean Evaluation conversion
)? I think since the type myname
is simple => String
, so it can be passed directly to print
.
If the method print
has changed:
def myname:String = "abc"
def print(name: String) = println(name)
print(myname)
It Evaluation conversion
certainly happened here, right? (From => String
to String
)
source to share
Quoting from §4.6.1 of the spec :
The type of such a parameter is the type of the method without parameters
=> T
.
So the type of pair is name-dependent (approximately) () => T
(or Function0[T]
if you prefer). If you are a :javap
method that takes a parameter by name, you will see that the compiled code takes a type parameter scala.Function0<java.lang.Object>
.
Approximation example
Transfer:
def callByName[T](f: => T) = f
callByName { /* magic */
1 + 1
/* ends here */ }
effectively:
def callByName[T](f: Function0[T]) = f.apply()
callByName(new Function0[Int] {
def apply() = { /* magic */
1 + 1
/* ends here */ }
})
Doubts surrounding the approach
You might be tempted to try to convey to () => T
your method. Try it callByName(() => 12)
; why doesn't it compile? (Hint, consider an extension on the call site). (Hover over the next space to see the answer):
The reason it
callByName(() => 12)
doesn't compile is because the extension is treated as: callByName (new Function0 [() => Int] {def apply () = () => 12}) That is, instead of passing inFunction0
which returnsInt
, you passFunction0
which returnsFunction0
which returnsInt
.
In fact => T
=> T
is actually the type of the method, not the object. So all that comes before is an approximation of what the compiler is doing and may change at any time. Quoting from §3.3 :
The types described below do not denote sets of values and do not appear explicitly in programs. They are presented in this report as internal types of specific identifiers.
So what are the types of methods? Quoting from §3.3.1 (MethodTypes) :
A special case is the types of methods without any parameters. They are written here
=> T
. Parametric methods are expressions that are reevaluated each time they reference a parameter name without parameters.Method types do not exist as value types. If a method name is used as a value, its type is implicitly converted to the corresponding function type ( §6.26 ).
And §6.26.3 (MethodConversions) :
The following four implicit conversions can be applied to methods that do not apply to the argument list.
Assessment . A parameterless
m
type method is=> T
always converted to a typeT
by evaluating the expression it is bound tom
.
Thus, the correct type translation is => T
always:
def random$name$here: T
Example
Here's an example class for the game:
class TestParamless {
def paramless: Int = 1
def callByName(f: => Int) = f
def example: Int = callByName(paramless)
}
Try new TestParamless().example
it as well :javap TestParamless
(in the scala REPL).
source to share