Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two ways of defining functions in Scala. What is the difference?

Here is a little Scala session that defines and tries out some functions:

scala> def test1(str: String) = str + str;     test1: (str: String)java.lang.String  scala> test1("ab") res0: java.lang.String = abab 

works nicely.

scala> val test2 = test1 <console>:6: error: missing arguments for method test1 in object $iw; follow this method with `_' if you want to treat it as a partially applied function        val test2 = test1                    ^ 

oops.

scala> val test2 = test1 _ test2: (String) => java.lang.String = <function1>  scala> test2("ab") res1: java.lang.String = abab 

works well!

Now, I've seen the _ syntax when folding (_ + _, etc). So as I understand it _ basically means "an argument". So test1 _ basically means a function with an argument, which is given to test1". But why isn't that exactly the same as just test1? Why is there a difference if I append a _?

So I kept exploring...

scala> val test3 = (str: String) => str + str test3: (String) => java.lang.String = <function1>  scala> test3("ab") res2: java.lang.String = abab  scala> val test4 = test3 test4: (String) => java.lang.String = <function1> 

Here it works without _! What's the difference between a defed function, and a valed function?

like image 823
aioobe Avatar asked Feb 15 '11 20:02

aioobe


People also ask

What is the difference between DEF and Val in Scala?

That's all about the difference between var, val, and def in Scala. In short, the val and var are evaluated when defined, while def is evaluated on call. Also, val defines a constant, a fixed value that cannot be modified once declared and assigned while var defines a variable, which can be modified or reassigned.

What are the functions in Scala?

In scala, functions are first class values. You can store function value, pass function as an argument and return function as a value from other function. You can create function by using def keyword. You must mention return type of parameters while defining function and return type of a function is optional.

What is the type of a function in Scala?

Here, Scala function is first-class value. Scala also has methods, but these differ only slightly from Scala function. A method belongs to a class; it has a name, a signature, [optionally, ] some annotations, and some bytecode. A function is a complete object that we can store in a variable.


2 Answers

The def declares a method within a surrounding object/class/trait, similar to the way you define methods in Java. You can only use defs within other objects/classes/traits. In the REPL, you cannot see the surrounding object because it's "hidden", but it does exist.

You cannot assign a def to a value, because the def is not a value - it's a method in the object.

The (x: T) => x * x declares and instantiates a function object, which exists at runtime. Function objects are instances of anonymous classes which extend FunctionN traits. FunctionN traits come with an apply method. The name apply is special, because it can be omitted. Expression f(x) is desugared into f.apply(x).

The bottomline is - since function objects are runtime values which exist on the heap, you can assign them to values, variables and parameters, or return them from methods as return values.

To solve the issue of assigning methods to values (which can be useful), Scala allows you to use the placeholder character to create a function object from a method. Expression test1 _ in your example above actually creates a wrapper function around the method test1 - it is equivalent to x => test1(x).

like image 157
axel22 Avatar answered Sep 20 '22 00:09

axel22


There's no difference between a def'ed function and a val'ed function:

scala> def test1 = (str: String) => str + str test1: (String) => java.lang.String  scala> val test2 = test1 test2: (String) => java.lang.String = <function1>  scala> val test3 = (str: String) => str + str test3: (String) => java.lang.String = <function1>  scala> val test4 = test2 test4: (String) => java.lang.String = <function1> 

See? All of these are functions, which is indicated by the X => Y type they have.

scala> def test5(str: String) = str + str test5: (str: String)java.lang.String 

Do you see an X => Y type? If you do, go see an ophthalmologist, because there's none. The type here is (X)Y, commonly used to denote a method.

Actually, test1, test2, test3 and test4 are all methods, which return functions. test5 is a method which returns a java.lang.String. Also, test1 through test4 do not take parameters (only test1 could, anyway), while test5 does.

So, the difference is pretty simple. In the first case, you tried to assign a method to a val, but did not fill in the parameters the method take. So it failed, until you added a trailing underscore, which meant turn my method into a function.

In the second example you had a function, so you didn't need to do anything else.

A method is not a function, and vice versa. A function is an object of one of the FunctionN classes. A method is a handle to some piece of code associated with an object.

See various questions about methods vs functions on Stack Overflow.

like image 33
Daniel C. Sobral Avatar answered Sep 21 '22 00:09

Daniel C. Sobral