Two ways to define functions in Scala. What is the difference?

Below is a small Scala session that defines and tries to perform some functions:

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

It works beautifully.

 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 good!

Now I saw the syntax _ when folding ( _ + _ , etc.). So, as I understand it, _ basically means "argument." So test1 _ basically means a function with an argument that is assigned to test1 ". But why is it not as accurate as test1 ? Why is there a difference if I add _ ?

So, I continued to study ...

 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 is the difference between def ed and val ed?

+42
function scala currying
Feb 15 '11 at 20:57
source share
3 answers

There is 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> 

Cm? These are all functions that are denoted by the type X => Y that they have.

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

Do you see type X => Y ? If so, contact your ophthalmologist because there is none. The type here is (X)Y , commonly used to denote a method.

Actually, test1 , test2 , test3 and test4 are all methods that return functions. test5 is a method that returns a java.lang.String . In addition, test1 test4 not accept parameters through test4 (perhaps only test1 ), while test5 does.

So the difference is pretty simple. In the first case, you tried to assign the val method, but did not fill in the parameters that the method accepts. So this did not succeed until you added a back underscore, which meant turning my method into a function.

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

The 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 versus functions in stack overflows.

+51
Feb 16 2018-11-11T00:
source share
โ€” -

def declares a method inside the surrounding object / class / trait, similar to how you define methods in Java. You can use def only for other objects / classes / features. In REPL, you cannot see the surrounding object because it is "hidden", but it exists.

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

(x: T) => x * x declares and instantiates a function object that exists at run time. Function objects are instances of anonymous classes that extend the features of FunctionN . FunctionN signs have an apply method. The name apply is special because it can be omitted. The expression f(x) is placed in f.apply(x) .

The bottom line is because function objects are run-time values โ€‹โ€‹that exist on the heap, you can assign them to values, variables and parameters, or return them from methods as return values.

To solve the problem of assigning values โ€‹โ€‹to methods (which may be useful), Scala allows you to use a placeholder to create a functional object from the method. The expression test1 _ in your example above actually creates a wrapper function around the method test1 - this is equivalent to x => test1(x) .

+58
Feb 15 2018-11-21T00:
source share

Underscore means different things in different contexts. But this can always be considered as a thing that will go here, but it does not need to be called.

When used instead of parameters, the effect is to raise the method to a function.

 scala> def test1(str: String) = str + str; test1: (str: String)java.lang.String scala> val f1 = test1 _ f1: (String) => java.lang.String = <function1> 

Note that the method has become a function of type (String) => String.

The difference between a method and a function in Scala is that the methods are similar to traditional Java methods. You cannot pass them as values. However, functions are values โ€‹โ€‹in their own right and can be used as input parameters and return values.

The climb can go further:

 scala> val f2 = f1 _ f2: () => (String) => java.lang.String = <function0> 

Raising this function leads to another function. This time is of type () => (String) => (String)

From what I can tell, this syntax is equivalent to substituting all parameters with an underscore explicitly. For example:

 scala> def add(i: Int, j: Int) = i + j add: (i: Int,j: Int)Int scala> val addF = add(_, _) addF: (Int, Int) => Int = <function2> scala> val addF2 = add _ addF2: (Int, Int) => Int = <function2> 
+11
Feb 15 '11 at 23:00
source share



All Articles