2

This example is from Beginning Scala, but it isn't really explained well enough for me.

val f: Int => String = x => "Dude: "+x

I have 2 questions really:

1) Is the first example identical to the code below:

val f = (x:Int) => "Dude: "+x

2) If so can someone elaborate, and dissect the first example a little bit. the String = x part throws me off. I'm not sure how to read the statement

3 Answers 3

9

They are the same. You are making scala's type inference work for you in two different ways.

In val f: Int => String = x => "Dude: "+x the part before the = sign is where you explicitly declare f of type Int => String (i.e. you're saying that f is a function that takes an input of type Int and returns a String) On the right side of the = you're assigning a value to f. The value (according to your declaration) must be a function that takes an Int and returns a String. In fact you are saying that f is equal to x => "Dude: "+x. The scala compiler's type inference is working for you, here, because it understands that x must be an Int from the fact you have declared f as a function from Int to String.

In val f = (x:Int) => "Dude: "+x you're letting scala's type inference "guess" what the type of f is by looking at the value you assign to it. This value (on the right side of the =) is a function that takes an Int (because you explicitly say that x:Int) and returns a String (because you add x to "Dude: ", which is a string, so the result of string + x must be a string itself).

Note: if you try the two versions in the REPL, you'll notice that in one case you will have f defined as (Int) => String, in the other as (Int) => java.lang.String They are (as of scala 2.8.1) the same thing: scala's String definition (in Predef.scala) is simply type String = java.lang.String. This was probably done for the version of scala that targeted the .NET framework (where String was likely an alias for .NET's System.String) so that you could always write String in your scala programs.

Sign up to request clarification or add additional context in comments.

4 Comments

Good catch about the second version returning a java.lang.String.
@Wilfred: thanks, but on second thought I removed my note. It's needless nitpicking and would just confuse the answer.
one vote for putting it back, at least as a parenthetical note. It makes interesting points about both inference and Java compatibility. My follow-up question would be, how do those two definitions differ from def f(x : Int) = "Dude: "+x
@Malvolio I put the note back. As for def vs val, with def you define a method, with val a function (which in scala is an object with methods of its own). They're not the same thing, but sometimes you can ignore the difference. Here's a good longer explanation. Here Martin Odersky himself chimes in to explain why they chose to create this duality.
5

Ok here we go:

line 1: val f: Int => String

reads as a function declared as a value with a signature that maps the first input value from a type Int to an output value of type String.

line 1: ... = x => "Dude: " + x

reads as a function definition using a lambda (or a function literal) that takes a parameter, called x, append it to a string "Dude: " and returns it. This definition is assigned to the value f. Since the value f was declared with Int => String, x will take on the type Int when the compiler infers its type. In Scala the last expression of a function body is the return statement, which also happens to be a String in this case, which fits our declaration. In addition, in Java and Scala, the operator + is overloaded. When you try to add a String to an Int, the result would be a string concatenation of the string value and the integer.

Now check this out:

line: 2 val f = (x:Int) => "Dude: " + x

This time around, f wasn't declared with a type, it's type is inferred from it's definition (x:Int) => "Dude: " + x, which is a function literal that takes a parameter named x of type Int and returns a String. It should be clear that the 2 versions are equivalent now.

Now as an exercise, try to write a few more versions that use the keyword def. When you are done, type all those f()s out in the REPL and observe their signatures. It should be clear as day by then.

1 Comment

This was also very helpful. Thank you
2

It's the same. The full version from which both of your versions are derived is this:

val f: Int => String = (x: Int) => "Dude:" + x

Section 6.23 of the language specification says that if the expected type of the parameters is known, then you can omit the type of the parameters in your anonymous function, which results in this:

val f: Int => String = (x) => "Dude:" + x

Then, quoting the specification: "In the case of a single untyped formal parameter, (x ) => e can be abbreviated to x => e." Which will result in this:

val f: Int => String = x => "Dude:" + x

... which is your first version.

However, if you do specify the types of the parameters in your anonymous function, in most cases Scala will be able to infer the type of your anonymous function, so there is no need to specify the type of the function explicitly. That doesn't mean it's wrong to do so. It's just redundant. So if you would drop the type definition of the variable holding your anonymous function, you get your second definition.

val f = (x: Int) => "Dude:" + x

You would expect that - given this - it should also be possible to define your function like this:

    scala> val f: Int => String = x: Int => "Dude:" + x      
<console>:1: error: identifier expected but string literal found.
       val f: Int => String = x: Int => "Dude:" + x

                                    ^

However, this will confuse the compiler. (The specification says something about it. I just haven't been able to find it yet.) If you do want to specify the parameter type of your anonymous function (as I said, there is not reason to do it), and you feel like omitting the parentheses, then this will work:

val f: Int => String = { x: Int => "Dude:" + x }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.