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

)

+3


source to share


1 answer


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 in Function0

which returns Int

, you pass Function0

which returns Function0

which returns Int

.

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 type T

by evaluating the expression it is bound to m

.

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).

+7


source







All Articles