Related
I read Scala Functions (part of Another tour of Scala). In that post he stated:
Methods and functions are not the same thing
But he didn't explain anything about it. What was he trying to say?
Jim has got this pretty much covered in his blog post, but I'm posting a briefing here for reference.
First, let's see what the Scala Specification tell us. Chapter 3 (types) tell us about Function Types (3.2.9) and Method Types (3.3.1). Chapter 4 (basic declarations) speaks of Value Declaration and Definitions (4.1), Variable Declaration and Definitions (4.2) and Functions Declarations and Definitions (4.6). Chapter 6 (expressions) speaks of Anonymous Functions (6.23) and Method Values (6.7). Curiously, function values is spoken of one time on 3.2.9, and no where else.
A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.
A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.
Value Declarations and Definitions and Variable Declarations and Definitions are val and var declarations, including both type and value - which can be, respectively, Function Type and Anonymous Functions or Method Values. Note that, on the JVM, these (method values) are implemented with what Java calls "methods".
A Function Declaration is a def declaration, including type and body. The type part is the Method Type, and the body is an expression or a block. This is also implemented on the JVM with what Java calls "methods".
Finally, an Anonymous Function is an instance of a Function Type (ie, an instance of the trait FunctionN), and a Method Value is the same thing! The distinction is that a Method Value is created from methods, either by postfixing an underscore (m _ is a method value corresponding to the "function declaration" (def) m), or by a process called eta-expansion, which is like an automatic cast from method to function.
That is what the specs say, so let me put this up-front: we do not use that terminology! It leads to too much confusion between so-called "function declaration", which is a part of the program (chapter 4 -- basic declarations) and "anonymous function", which is an expression, and "function type", which is, well a type -- a trait.
The terminology below, and used by experienced Scala programmers, makes one change from the terminology of the specification: instead of saying function declaration, we say method. Or even method declaration. Furthermore, we note that value declarations and variable declarations are also methods for practical purposes.
So, given the above change in terminology, here's a practical explanation of the distinction.
A function is an object that includes one of the FunctionX traits, such as Function0, Function1, Function2, etc. It might be including PartialFunction as well, which actually extends Function1.
Let's see the type signature for one of these traits:
trait Function2[-T1, -T2, +R] extends AnyRef
This trait has one abstract method (it has a few concrete methods as well):
def apply(v1: T1, v2: T2): R
And that tell us all that there is to know about it. A function has an apply method which receives N parameters of types T1, T2, ..., TN, and returns something of type R. It is contra-variant on the parameters it receives, and co-variant on the result.
That variance means that a Function1[Seq[T], String] is a subtype of Function1[List[T], AnyRef]. Being a subtype means it can be used in place of it. One can easily see that if I'm going to call f(List(1, 2, 3)) and expect an AnyRef back, either of the two types above would work.
Now, what is the similarity of a method and a function? Well, if f is a function and m is a method local to the scope, then both can be called like this:
val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))
These calls are actually different, because the first one is just a syntactic sugar. Scala expands it to:
val o1 = f.apply(List(1, 2, 3))
Which, of course, is a method call on object f. Functions also have other syntactic sugars to its advantage: function literals (two of them, actually) and (T1, T2) => R type signatures. For example:
val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
case i: Int => "Int"
case d: Double => "Double"
case o => "Other"
}
Another similarity between a method and a function is that the former can be easily converted into the latter:
val f = m _
Scala will expand that, assuming m type is (List[Int])AnyRef into (Scala 2.7):
val f = new AnyRef with Function1[List[Int], AnyRef] {
def apply(x$1: List[Int]) = this.m(x$1)
}
On Scala 2.8, it actually uses an AbstractFunction1 class to reduce class sizes.
Notice that one can't convert the other way around -- from a function to a method.
Methods, however, have one big advantage (well, two -- they can be slightly faster): they can receive type parameters. For instance, while f above can necessarily specify the type of List it receives (List[Int] in the example), m can parameterize it:
def m[T](l: List[T]): String = l mkString ""
I think this pretty much covers everything, but I'll be happy to complement this with answers to any questions that may remain.
One big practical difference between a method and a function is what return means. return only ever returns from a method. For example:
scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
val f = () => { return "test" }
^
Returning from a function defined in a method does a non-local return:
scala> def f: String = {
| val g = () => { return "test" }
| g()
| "not this"
| }
f: String
scala> f
res4: String = test
Whereas returning from a local method only returns from that method.
scala> def f2: String = {
| def g(): String = { return "test" }
| g()
| "is this"
| }
f2: String
scala> f2
res5: String = is this
function A function can be invoked with a list of arguments to produce a
result. A function has a parameter list, a body, and a result type.
Functions that are members of a class, trait, or singleton object are
called methods. Functions defined inside other functions are called
local functions. Functions with the result type of Unit are called procedures.
Anonymous functions in source code are called function literals.
At run time, function literals are instantiated into objects called
function values.
Programming in Scala Second Edition.
Martin Odersky - Lex Spoon - Bill Venners
Let Say you have a List
scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
Define a Method
scala> def m1(i:Int)=i+2
m1: (i: Int)Int
Define a Function
scala> (i:Int)=>i+2
res0: Int => Int = <function1>
scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Method Accepting Argument
scala> m1(2)
res3: Int = 4
Defining Function with val
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>
Argument to function is Optional
scala> p(2)
res4: Int = 4
scala> p
res5: Int => Int = <function1>
Argument to Method is Mandatory
scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
Check the following Tutorial that explains passing other differences with examples like other example of diff with Method Vs Function, Using function as Variables, creating function that returned function
Functions don't support parameter defaults. Methods do. Converting from a method to a function loses parameter defaults. (Scala 2.8.1)
There is a nice article here from which most of my descriptions are taken.
Just a short comparison of Functions and Methods regarding my understanding. Hope it helps:
Functions:
They are basically an object. More precisely, functions are objects with an apply method; Therefore, they are a little bit slower than methods because of their overhead. It is similar to static methods in the sense that they are independent of an object to be invoked.
A simple example of a function is just like bellow:
val f1 = (x: Int) => x + x
f1(2) // 4
The line above is nothing except assigning one object to another like object1 = object2. Actually the object2 in our example is an anonymous function and the left side gets the type of an object because of that. Therefore, now f1 is an object(Function). The anonymous function is actually an instance of Function1[Int, Int] that means a function with 1 parameter of type Int and return value of type Int.
Calling f1 without the arguments will give us the signature of the anonymous function (Int => Int = )
Methods:
They are not objects but assigned to an instance of a class,i.e., an object. Exactly the same as method in java or member functions in c++ (as Raffi Khatchadourian pointed out in a comment to this question) and etc.
A simple example of a method is just like bellow:
def m1(x: Int) = x + x
m1(2) // 4
The line above is not a simple value assignment but a definition of a method. When you invoke this method with the value 2 like the second line, the x is substituted with 2 and the result will be calculated and you get 4 as an output. Here you will get an error if just simply write m1 because it is method and need the input value. By using _ you can assign a method to a function like bellow:
val f2 = m1 _ // Int => Int = <function1>
Here is a great post by Rob Norris which explains the difference, here is a TL;DR
Methods in Scala are not values, but functions are. You can construct a function that delegates to a method via η-expansion (triggered by the trailing underscore thingy).
with the following definition:
a method is something defined with def and a value is something you can assign to a val
In a nutshell (extract from the blog):
When we define a method we see that we cannot assign it to a val.
scala> def add1(n: Int): Int = n + 1
add1: (n: Int)Int
scala> val f = add1
<console>:8: error: missing arguments for method add1;
follow this method with `_' if you want to treat it as a partially applied function
val f = add1
Note also the type of add1, which doesn’t look normal; you can’t declare a variable of type (n: Int)Int. Methods are not values.
However, by adding the η-expansion postfix operator (η is pronounced “eta”), we can turn the method into a function value. Note the type of f.
scala> val f = add1 _
f: Int => Int = <function1>
scala> f(3)
res0: Int = 4
The effect of _ is to perform the equivalent of the following: we construct a Function1 instance that delegates to our method.
scala> val g = new Function1[Int, Int] { def apply(n: Int): Int = add1(n) }
g: Int => Int = <function1>
scala> g(3)
res18: Int = 4
Practically, a Scala programmer only needs to know the following three rules to use functions and methods properly:
Methods defined by def and function literals defined by => are functions. It is defined in page 143, Chapter 8 in the book of Programming in Scala, 4th edition.
Function values are objects that can be passed around as any values. Function literals and partially applied functions are function values.
You can leave off the underscore of a partially applied function if a function value is required at a point in the code. For example: someNumber.foreach(println)
After four editions of Programming in Scala, it is still an issue for people to differentiate the two important concepts: function and function value because all editions don't give a clear explanation. The language specification is too complicated. I found the above rules are simple and accurate.
In Scala 2.13, unlike functions, methods can take/return
type parameters (polymorphic methods)
implicit parameters
dependent types
However, these restrictions are lifted in dotty (Scala 3) by Polymorphic function types #4672, for example, dotty version 0.23.0-RC1 enables the following syntax
Type parameters
def fmet[T](x: List[T]) = x.map(e => (e, e))
val ffun = [T] => (x: List[T]) => x.map(e => (e, e))
Implicit parameters (context parameters)
def gmet[T](implicit num: Numeric[T]): T = num.zero
val gfun: [T] => Numeric[T] ?=> T = [T] => (using num: Numeric[T]) => num.zero
Dependent types
class A { class B }
def hmet(a: A): a.B = new a.B
val hfun: (a: A) => a.B = hmet
For more examples, see tests/run/polymorphic-functions.scala
The difference is subtle but substantial and it is related to the type system in use (besides the nomenclature coming from Object Oriented or Functional paradigm).
When we talk about a function, we talk about the type Function: it being a type, an instance of it can be passed around as input or output to other functions (at least in the case of Scala).
When we talk about a method (of a class), we are actually talking about the type represented by the class it is part of: that is, the method is just a component of a larger type, and cannot be passed around by itself. It must be passed around with the instance of the type it is part of (i.e. the instance of the class).
A method belongs to an object (usually the class, trait or object in which you define it), whereas a function is by itself a value, and because in Scala every value is an object, therefore, a function is an object.
For example, given a method and a function below:
def timesTwoMethod(x :Int): Int = x * 2
def timesTwoFunction = (x: Int) => x * 2
The second def is an object of type Int => Int (the syntactic sugar for Function1[Int, Int]).
Scala made functions objects so they could be used as first-class entities. This way you can pass functions to other functions as arguments.
However, Scala can also treat methods as functions via a mechanism called Eta Expansion.
For example, the higher-order function map defined on List, receives another function f: A => B as its only parameter. The next two lines are equivalent:
List(1, 2, 3).map(timesTwoMethod)
List(1, 2, 3).map(timesTwoFunction)
When the compiler sees a def given in a place where a function is needed, it automatically converts the method into an equivalent function.
A method operates on an object but a function doesn't.
Scala and C++ has Fuction but in JAVA, you have to imitate them with static methods.
I read Scala Functions (part of Another tour of Scala). In that post he stated:
Methods and functions are not the same thing
But he didn't explain anything about it. What was he trying to say?
Jim has got this pretty much covered in his blog post, but I'm posting a briefing here for reference.
First, let's see what the Scala Specification tell us. Chapter 3 (types) tell us about Function Types (3.2.9) and Method Types (3.3.1). Chapter 4 (basic declarations) speaks of Value Declaration and Definitions (4.1), Variable Declaration and Definitions (4.2) and Functions Declarations and Definitions (4.6). Chapter 6 (expressions) speaks of Anonymous Functions (6.23) and Method Values (6.7). Curiously, function values is spoken of one time on 3.2.9, and no where else.
A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.
A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.
Value Declarations and Definitions and Variable Declarations and Definitions are val and var declarations, including both type and value - which can be, respectively, Function Type and Anonymous Functions or Method Values. Note that, on the JVM, these (method values) are implemented with what Java calls "methods".
A Function Declaration is a def declaration, including type and body. The type part is the Method Type, and the body is an expression or a block. This is also implemented on the JVM with what Java calls "methods".
Finally, an Anonymous Function is an instance of a Function Type (ie, an instance of the trait FunctionN), and a Method Value is the same thing! The distinction is that a Method Value is created from methods, either by postfixing an underscore (m _ is a method value corresponding to the "function declaration" (def) m), or by a process called eta-expansion, which is like an automatic cast from method to function.
That is what the specs say, so let me put this up-front: we do not use that terminology! It leads to too much confusion between so-called "function declaration", which is a part of the program (chapter 4 -- basic declarations) and "anonymous function", which is an expression, and "function type", which is, well a type -- a trait.
The terminology below, and used by experienced Scala programmers, makes one change from the terminology of the specification: instead of saying function declaration, we say method. Or even method declaration. Furthermore, we note that value declarations and variable declarations are also methods for practical purposes.
So, given the above change in terminology, here's a practical explanation of the distinction.
A function is an object that includes one of the FunctionX traits, such as Function0, Function1, Function2, etc. It might be including PartialFunction as well, which actually extends Function1.
Let's see the type signature for one of these traits:
trait Function2[-T1, -T2, +R] extends AnyRef
This trait has one abstract method (it has a few concrete methods as well):
def apply(v1: T1, v2: T2): R
And that tell us all that there is to know about it. A function has an apply method which receives N parameters of types T1, T2, ..., TN, and returns something of type R. It is contra-variant on the parameters it receives, and co-variant on the result.
That variance means that a Function1[Seq[T], String] is a subtype of Function1[List[T], AnyRef]. Being a subtype means it can be used in place of it. One can easily see that if I'm going to call f(List(1, 2, 3)) and expect an AnyRef back, either of the two types above would work.
Now, what is the similarity of a method and a function? Well, if f is a function and m is a method local to the scope, then both can be called like this:
val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))
These calls are actually different, because the first one is just a syntactic sugar. Scala expands it to:
val o1 = f.apply(List(1, 2, 3))
Which, of course, is a method call on object f. Functions also have other syntactic sugars to its advantage: function literals (two of them, actually) and (T1, T2) => R type signatures. For example:
val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
case i: Int => "Int"
case d: Double => "Double"
case o => "Other"
}
Another similarity between a method and a function is that the former can be easily converted into the latter:
val f = m _
Scala will expand that, assuming m type is (List[Int])AnyRef into (Scala 2.7):
val f = new AnyRef with Function1[List[Int], AnyRef] {
def apply(x$1: List[Int]) = this.m(x$1)
}
On Scala 2.8, it actually uses an AbstractFunction1 class to reduce class sizes.
Notice that one can't convert the other way around -- from a function to a method.
Methods, however, have one big advantage (well, two -- they can be slightly faster): they can receive type parameters. For instance, while f above can necessarily specify the type of List it receives (List[Int] in the example), m can parameterize it:
def m[T](l: List[T]): String = l mkString ""
I think this pretty much covers everything, but I'll be happy to complement this with answers to any questions that may remain.
One big practical difference between a method and a function is what return means. return only ever returns from a method. For example:
scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
val f = () => { return "test" }
^
Returning from a function defined in a method does a non-local return:
scala> def f: String = {
| val g = () => { return "test" }
| g()
| "not this"
| }
f: String
scala> f
res4: String = test
Whereas returning from a local method only returns from that method.
scala> def f2: String = {
| def g(): String = { return "test" }
| g()
| "is this"
| }
f2: String
scala> f2
res5: String = is this
function A function can be invoked with a list of arguments to produce a
result. A function has a parameter list, a body, and a result type.
Functions that are members of a class, trait, or singleton object are
called methods. Functions defined inside other functions are called
local functions. Functions with the result type of Unit are called procedures.
Anonymous functions in source code are called function literals.
At run time, function literals are instantiated into objects called
function values.
Programming in Scala Second Edition.
Martin Odersky - Lex Spoon - Bill Venners
Let Say you have a List
scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
Define a Method
scala> def m1(i:Int)=i+2
m1: (i: Int)Int
Define a Function
scala> (i:Int)=>i+2
res0: Int => Int = <function1>
scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Method Accepting Argument
scala> m1(2)
res3: Int = 4
Defining Function with val
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>
Argument to function is Optional
scala> p(2)
res4: Int = 4
scala> p
res5: Int => Int = <function1>
Argument to Method is Mandatory
scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
Check the following Tutorial that explains passing other differences with examples like other example of diff with Method Vs Function, Using function as Variables, creating function that returned function
Functions don't support parameter defaults. Methods do. Converting from a method to a function loses parameter defaults. (Scala 2.8.1)
There is a nice article here from which most of my descriptions are taken.
Just a short comparison of Functions and Methods regarding my understanding. Hope it helps:
Functions:
They are basically an object. More precisely, functions are objects with an apply method; Therefore, they are a little bit slower than methods because of their overhead. It is similar to static methods in the sense that they are independent of an object to be invoked.
A simple example of a function is just like bellow:
val f1 = (x: Int) => x + x
f1(2) // 4
The line above is nothing except assigning one object to another like object1 = object2. Actually the object2 in our example is an anonymous function and the left side gets the type of an object because of that. Therefore, now f1 is an object(Function). The anonymous function is actually an instance of Function1[Int, Int] that means a function with 1 parameter of type Int and return value of type Int.
Calling f1 without the arguments will give us the signature of the anonymous function (Int => Int = )
Methods:
They are not objects but assigned to an instance of a class,i.e., an object. Exactly the same as method in java or member functions in c++ (as Raffi Khatchadourian pointed out in a comment to this question) and etc.
A simple example of a method is just like bellow:
def m1(x: Int) = x + x
m1(2) // 4
The line above is not a simple value assignment but a definition of a method. When you invoke this method with the value 2 like the second line, the x is substituted with 2 and the result will be calculated and you get 4 as an output. Here you will get an error if just simply write m1 because it is method and need the input value. By using _ you can assign a method to a function like bellow:
val f2 = m1 _ // Int => Int = <function1>
Here is a great post by Rob Norris which explains the difference, here is a TL;DR
Methods in Scala are not values, but functions are. You can construct a function that delegates to a method via η-expansion (triggered by the trailing underscore thingy).
with the following definition:
a method is something defined with def and a value is something you can assign to a val
In a nutshell (extract from the blog):
When we define a method we see that we cannot assign it to a val.
scala> def add1(n: Int): Int = n + 1
add1: (n: Int)Int
scala> val f = add1
<console>:8: error: missing arguments for method add1;
follow this method with `_' if you want to treat it as a partially applied function
val f = add1
Note also the type of add1, which doesn’t look normal; you can’t declare a variable of type (n: Int)Int. Methods are not values.
However, by adding the η-expansion postfix operator (η is pronounced “eta”), we can turn the method into a function value. Note the type of f.
scala> val f = add1 _
f: Int => Int = <function1>
scala> f(3)
res0: Int = 4
The effect of _ is to perform the equivalent of the following: we construct a Function1 instance that delegates to our method.
scala> val g = new Function1[Int, Int] { def apply(n: Int): Int = add1(n) }
g: Int => Int = <function1>
scala> g(3)
res18: Int = 4
Practically, a Scala programmer only needs to know the following three rules to use functions and methods properly:
Methods defined by def and function literals defined by => are functions. It is defined in page 143, Chapter 8 in the book of Programming in Scala, 4th edition.
Function values are objects that can be passed around as any values. Function literals and partially applied functions are function values.
You can leave off the underscore of a partially applied function if a function value is required at a point in the code. For example: someNumber.foreach(println)
After four editions of Programming in Scala, it is still an issue for people to differentiate the two important concepts: function and function value because all editions don't give a clear explanation. The language specification is too complicated. I found the above rules are simple and accurate.
In Scala 2.13, unlike functions, methods can take/return
type parameters (polymorphic methods)
implicit parameters
dependent types
However, these restrictions are lifted in dotty (Scala 3) by Polymorphic function types #4672, for example, dotty version 0.23.0-RC1 enables the following syntax
Type parameters
def fmet[T](x: List[T]) = x.map(e => (e, e))
val ffun = [T] => (x: List[T]) => x.map(e => (e, e))
Implicit parameters (context parameters)
def gmet[T](implicit num: Numeric[T]): T = num.zero
val gfun: [T] => Numeric[T] ?=> T = [T] => (using num: Numeric[T]) => num.zero
Dependent types
class A { class B }
def hmet(a: A): a.B = new a.B
val hfun: (a: A) => a.B = hmet
For more examples, see tests/run/polymorphic-functions.scala
The difference is subtle but substantial and it is related to the type system in use (besides the nomenclature coming from Object Oriented or Functional paradigm).
When we talk about a function, we talk about the type Function: it being a type, an instance of it can be passed around as input or output to other functions (at least in the case of Scala).
When we talk about a method (of a class), we are actually talking about the type represented by the class it is part of: that is, the method is just a component of a larger type, and cannot be passed around by itself. It must be passed around with the instance of the type it is part of (i.e. the instance of the class).
A method belongs to an object (usually the class, trait or object in which you define it), whereas a function is by itself a value, and because in Scala every value is an object, therefore, a function is an object.
For example, given a method and a function below:
def timesTwoMethod(x :Int): Int = x * 2
def timesTwoFunction = (x: Int) => x * 2
The second def is an object of type Int => Int (the syntactic sugar for Function1[Int, Int]).
Scala made functions objects so they could be used as first-class entities. This way you can pass functions to other functions as arguments.
However, Scala can also treat methods as functions via a mechanism called Eta Expansion.
For example, the higher-order function map defined on List, receives another function f: A => B as its only parameter. The next two lines are equivalent:
List(1, 2, 3).map(timesTwoMethod)
List(1, 2, 3).map(timesTwoFunction)
When the compiler sees a def given in a place where a function is needed, it automatically converts the method into an equivalent function.
A method operates on an object but a function doesn't.
Scala and C++ has Fuction but in JAVA, you have to imitate them with static methods.
I read Scala Functions (part of Another tour of Scala). In that post he stated:
Methods and functions are not the same thing
But he didn't explain anything about it. What was he trying to say?
Jim has got this pretty much covered in his blog post, but I'm posting a briefing here for reference.
First, let's see what the Scala Specification tell us. Chapter 3 (types) tell us about Function Types (3.2.9) and Method Types (3.3.1). Chapter 4 (basic declarations) speaks of Value Declaration and Definitions (4.1), Variable Declaration and Definitions (4.2) and Functions Declarations and Definitions (4.6). Chapter 6 (expressions) speaks of Anonymous Functions (6.23) and Method Values (6.7). Curiously, function values is spoken of one time on 3.2.9, and no where else.
A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.
A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.
Value Declarations and Definitions and Variable Declarations and Definitions are val and var declarations, including both type and value - which can be, respectively, Function Type and Anonymous Functions or Method Values. Note that, on the JVM, these (method values) are implemented with what Java calls "methods".
A Function Declaration is a def declaration, including type and body. The type part is the Method Type, and the body is an expression or a block. This is also implemented on the JVM with what Java calls "methods".
Finally, an Anonymous Function is an instance of a Function Type (ie, an instance of the trait FunctionN), and a Method Value is the same thing! The distinction is that a Method Value is created from methods, either by postfixing an underscore (m _ is a method value corresponding to the "function declaration" (def) m), or by a process called eta-expansion, which is like an automatic cast from method to function.
That is what the specs say, so let me put this up-front: we do not use that terminology! It leads to too much confusion between so-called "function declaration", which is a part of the program (chapter 4 -- basic declarations) and "anonymous function", which is an expression, and "function type", which is, well a type -- a trait.
The terminology below, and used by experienced Scala programmers, makes one change from the terminology of the specification: instead of saying function declaration, we say method. Or even method declaration. Furthermore, we note that value declarations and variable declarations are also methods for practical purposes.
So, given the above change in terminology, here's a practical explanation of the distinction.
A function is an object that includes one of the FunctionX traits, such as Function0, Function1, Function2, etc. It might be including PartialFunction as well, which actually extends Function1.
Let's see the type signature for one of these traits:
trait Function2[-T1, -T2, +R] extends AnyRef
This trait has one abstract method (it has a few concrete methods as well):
def apply(v1: T1, v2: T2): R
And that tell us all that there is to know about it. A function has an apply method which receives N parameters of types T1, T2, ..., TN, and returns something of type R. It is contra-variant on the parameters it receives, and co-variant on the result.
That variance means that a Function1[Seq[T], String] is a subtype of Function1[List[T], AnyRef]. Being a subtype means it can be used in place of it. One can easily see that if I'm going to call f(List(1, 2, 3)) and expect an AnyRef back, either of the two types above would work.
Now, what is the similarity of a method and a function? Well, if f is a function and m is a method local to the scope, then both can be called like this:
val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))
These calls are actually different, because the first one is just a syntactic sugar. Scala expands it to:
val o1 = f.apply(List(1, 2, 3))
Which, of course, is a method call on object f. Functions also have other syntactic sugars to its advantage: function literals (two of them, actually) and (T1, T2) => R type signatures. For example:
val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
case i: Int => "Int"
case d: Double => "Double"
case o => "Other"
}
Another similarity between a method and a function is that the former can be easily converted into the latter:
val f = m _
Scala will expand that, assuming m type is (List[Int])AnyRef into (Scala 2.7):
val f = new AnyRef with Function1[List[Int], AnyRef] {
def apply(x$1: List[Int]) = this.m(x$1)
}
On Scala 2.8, it actually uses an AbstractFunction1 class to reduce class sizes.
Notice that one can't convert the other way around -- from a function to a method.
Methods, however, have one big advantage (well, two -- they can be slightly faster): they can receive type parameters. For instance, while f above can necessarily specify the type of List it receives (List[Int] in the example), m can parameterize it:
def m[T](l: List[T]): String = l mkString ""
I think this pretty much covers everything, but I'll be happy to complement this with answers to any questions that may remain.
One big practical difference between a method and a function is what return means. return only ever returns from a method. For example:
scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
val f = () => { return "test" }
^
Returning from a function defined in a method does a non-local return:
scala> def f: String = {
| val g = () => { return "test" }
| g()
| "not this"
| }
f: String
scala> f
res4: String = test
Whereas returning from a local method only returns from that method.
scala> def f2: String = {
| def g(): String = { return "test" }
| g()
| "is this"
| }
f2: String
scala> f2
res5: String = is this
function A function can be invoked with a list of arguments to produce a
result. A function has a parameter list, a body, and a result type.
Functions that are members of a class, trait, or singleton object are
called methods. Functions defined inside other functions are called
local functions. Functions with the result type of Unit are called procedures.
Anonymous functions in source code are called function literals.
At run time, function literals are instantiated into objects called
function values.
Programming in Scala Second Edition.
Martin Odersky - Lex Spoon - Bill Venners
Let Say you have a List
scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
Define a Method
scala> def m1(i:Int)=i+2
m1: (i: Int)Int
Define a Function
scala> (i:Int)=>i+2
res0: Int => Int = <function1>
scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Method Accepting Argument
scala> m1(2)
res3: Int = 4
Defining Function with val
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>
Argument to function is Optional
scala> p(2)
res4: Int = 4
scala> p
res5: Int => Int = <function1>
Argument to Method is Mandatory
scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
Check the following Tutorial that explains passing other differences with examples like other example of diff with Method Vs Function, Using function as Variables, creating function that returned function
Functions don't support parameter defaults. Methods do. Converting from a method to a function loses parameter defaults. (Scala 2.8.1)
There is a nice article here from which most of my descriptions are taken.
Just a short comparison of Functions and Methods regarding my understanding. Hope it helps:
Functions:
They are basically an object. More precisely, functions are objects with an apply method; Therefore, they are a little bit slower than methods because of their overhead. It is similar to static methods in the sense that they are independent of an object to be invoked.
A simple example of a function is just like bellow:
val f1 = (x: Int) => x + x
f1(2) // 4
The line above is nothing except assigning one object to another like object1 = object2. Actually the object2 in our example is an anonymous function and the left side gets the type of an object because of that. Therefore, now f1 is an object(Function). The anonymous function is actually an instance of Function1[Int, Int] that means a function with 1 parameter of type Int and return value of type Int.
Calling f1 without the arguments will give us the signature of the anonymous function (Int => Int = )
Methods:
They are not objects but assigned to an instance of a class,i.e., an object. Exactly the same as method in java or member functions in c++ (as Raffi Khatchadourian pointed out in a comment to this question) and etc.
A simple example of a method is just like bellow:
def m1(x: Int) = x + x
m1(2) // 4
The line above is not a simple value assignment but a definition of a method. When you invoke this method with the value 2 like the second line, the x is substituted with 2 and the result will be calculated and you get 4 as an output. Here you will get an error if just simply write m1 because it is method and need the input value. By using _ you can assign a method to a function like bellow:
val f2 = m1 _ // Int => Int = <function1>
Here is a great post by Rob Norris which explains the difference, here is a TL;DR
Methods in Scala are not values, but functions are. You can construct a function that delegates to a method via η-expansion (triggered by the trailing underscore thingy).
with the following definition:
a method is something defined with def and a value is something you can assign to a val
In a nutshell (extract from the blog):
When we define a method we see that we cannot assign it to a val.
scala> def add1(n: Int): Int = n + 1
add1: (n: Int)Int
scala> val f = add1
<console>:8: error: missing arguments for method add1;
follow this method with `_' if you want to treat it as a partially applied function
val f = add1
Note also the type of add1, which doesn’t look normal; you can’t declare a variable of type (n: Int)Int. Methods are not values.
However, by adding the η-expansion postfix operator (η is pronounced “eta”), we can turn the method into a function value. Note the type of f.
scala> val f = add1 _
f: Int => Int = <function1>
scala> f(3)
res0: Int = 4
The effect of _ is to perform the equivalent of the following: we construct a Function1 instance that delegates to our method.
scala> val g = new Function1[Int, Int] { def apply(n: Int): Int = add1(n) }
g: Int => Int = <function1>
scala> g(3)
res18: Int = 4
Practically, a Scala programmer only needs to know the following three rules to use functions and methods properly:
Methods defined by def and function literals defined by => are functions. It is defined in page 143, Chapter 8 in the book of Programming in Scala, 4th edition.
Function values are objects that can be passed around as any values. Function literals and partially applied functions are function values.
You can leave off the underscore of a partially applied function if a function value is required at a point in the code. For example: someNumber.foreach(println)
After four editions of Programming in Scala, it is still an issue for people to differentiate the two important concepts: function and function value because all editions don't give a clear explanation. The language specification is too complicated. I found the above rules are simple and accurate.
In Scala 2.13, unlike functions, methods can take/return
type parameters (polymorphic methods)
implicit parameters
dependent types
However, these restrictions are lifted in dotty (Scala 3) by Polymorphic function types #4672, for example, dotty version 0.23.0-RC1 enables the following syntax
Type parameters
def fmet[T](x: List[T]) = x.map(e => (e, e))
val ffun = [T] => (x: List[T]) => x.map(e => (e, e))
Implicit parameters (context parameters)
def gmet[T](implicit num: Numeric[T]): T = num.zero
val gfun: [T] => Numeric[T] ?=> T = [T] => (using num: Numeric[T]) => num.zero
Dependent types
class A { class B }
def hmet(a: A): a.B = new a.B
val hfun: (a: A) => a.B = hmet
For more examples, see tests/run/polymorphic-functions.scala
The difference is subtle but substantial and it is related to the type system in use (besides the nomenclature coming from Object Oriented or Functional paradigm).
When we talk about a function, we talk about the type Function: it being a type, an instance of it can be passed around as input or output to other functions (at least in the case of Scala).
When we talk about a method (of a class), we are actually talking about the type represented by the class it is part of: that is, the method is just a component of a larger type, and cannot be passed around by itself. It must be passed around with the instance of the type it is part of (i.e. the instance of the class).
A method belongs to an object (usually the class, trait or object in which you define it), whereas a function is by itself a value, and because in Scala every value is an object, therefore, a function is an object.
For example, given a method and a function below:
def timesTwoMethod(x :Int): Int = x * 2
def timesTwoFunction = (x: Int) => x * 2
The second def is an object of type Int => Int (the syntactic sugar for Function1[Int, Int]).
Scala made functions objects so they could be used as first-class entities. This way you can pass functions to other functions as arguments.
However, Scala can also treat methods as functions via a mechanism called Eta Expansion.
For example, the higher-order function map defined on List, receives another function f: A => B as its only parameter. The next two lines are equivalent:
List(1, 2, 3).map(timesTwoMethod)
List(1, 2, 3).map(timesTwoFunction)
When the compiler sees a def given in a place where a function is needed, it automatically converts the method into an equivalent function.
A method operates on an object but a function doesn't.
Scala and C++ has Fuction but in JAVA, you have to imitate them with static methods.
I'm looking for a function:
def fun(init:Int,level:Int)
Such that:
fun(1,1) == List(1)
fun(1,2) == List(List(1),List(1))
This task is very easy in java by using a for iteration. How can I write it in Scala using the functional programing style?
You can use List.fill for this. The first parameter list of this method has many overloads of variable length, and represents the number of elements at each level of nesting. The second argument is the element to fill:
List.fill(1, 1)(1) //List(List(1))
List.fill(1, 2, 3)(4) //List(List(List(4, 4, 4), List(4, 4, 4)))
The full method definition you're looking for doesn't fit very well in to Scala, because the return type would be the least common super type of List[Int], List[List[Int]], List[List[List[Int]]], etc.), which would be Any or List[Any] depending on your definition of fun(1, 0). It would look something like this:
def fun(init: Int, level: Int): Any = level match {
case 0 => init
case n => List(fun(init, level - 1))
}
But this really isn't recommended and would be considered unidiomatic in most Scala environments.
You can solve it with the help of a recursive function:
def fun(init:Int, level:Int):List[_] = {
if(level <= 1)
List(init)
else
List.make(level, fun(init, level-1))
}
At every level it creates a list with the same number of elements as the level is by using the make function of the List object. The Elements you are creating are also Lists whith one element less then the current level is. The end condition of your function is when the number is smaller or equal to 1. That's the moment you simply return a list with the init value as Element.
A type-safe approach involves the use of a tree for instance defined as follows,
trait Tree
case class Branch(t: List[Tree]) extends Tree
case class Leaf(i: Int) extends Tree
Then for example
val tree1 = Branch(List( Branch(List(Leaf(1),Leaf(2))), Leaf(3)))
where each consecutive Branch(List()) pattern corresponds to 1 level.
Looking at Programming in Scala (control abstraction) I saw these two examples that have the same effect:
1. Higher-Order Function
def withPrintWriter(file: File, op: PrintWriter => Unit) {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
2. Currying function
def withPrintWriter(file: File)(op: PrintWriter => Unit) {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
What is the difference between them? Can we always achieve the same result in both ways?
The concepts of higher-order functions and curried functions are generally used in an orthogonal way. A higher-order function is simply a function that takes a function as an argument or returns a function as a result, and it may or may not be curried. In general usage, someone referring to a higher-order function is usually talking about a function that takes another function as an argument.
A curried function, on the other hand, is one that returns a function as its result. A fully curried function is a one-argument function that either returns an ordinary result or returns a fully curried function. Note that a curried function is necessarily a higher-order function, since it returns a function as its result.
Thus, your second example is an example of a curried function that returns a higher-order function. Here's another example of curried function that does not take a function as an argument, expressed in various (nearly equivalent) ways:
def plus(a: Int)(b:Int) = a + b
def plus(a: Int) = (b: Int) => a + b
val plus = (a: Int) => (b: Int) => a + b
Higher order functions are functions that either take functions as parameter or return functions or both.
def f(g: Int => Int) = g(_: Int) + 23
scala> f(_ + 45)
res1: Int => Int = <function1>
scala> res1(4)
res2: Int = 72
This is a higher order function, it takes a function as parameter and returns another function. As you can see, higher order functions are a pre-requisite for currying. The curry function looks like this:
def curry[A,B,C](f: (A,B) => C) = (a: A) => (b: B) => f(a,b)
scala> curry((a: Int, b: Int) => a+b)
res3: Int => (Int => Int) = <function1>
scala> res3(3)
res4: Int => Int = <function1>
scala> res4(3)
res5: Int = 6
So to answer your question: They are two different concepts, where the one (higher order functions) is the pre-requisit for the other (currying).
Semantically, there is one difference I can think of between a curried and a not curried function. With the non-curried version, when you call withPrintWriter, that's a single method call. With the curried version, it's actually going to be two method calls. Think of it like this:
withPrintWriter.apply(file).apply(op)
Other than that, I think a lot of people use currying in this kind of situation for style. Using currying here makes this look more like a language feature then just a custom function call because you can use it like this:
withPrintWriter(file){ op =>
...
}
Using it in that way is trying to emulate some sore of control structure from the language itself, but again, this is only really a style thing and it does come with the overhead of an additional method call.
You can use the non-curried version in almost the same way, but it's not as clean looking:
withPrintWriter(file, { op =>
...
})
EDIT
#drexin makes a good point in his answer that it's worth mentioning here for me. When you think of the signature of the curried version of the method, it's really:
Function1[File, Function1[PrintWriter, Unit]]
They are mostly the same, but there is a difference with regard to type inference. Scala is not able to infer types between arguments of a single method invocation, but it is able to infer types for multiple argument lists.
Consider:
def foo1[T](x : T, y : T => T) = y(x)
def foo2[T](x : T)(y : T => T) = y(x)
foo1(1, t => t + 1) //does not compile with 'missing parameter type'
foo2(1)(t => t + 1) //compiles
You can see some additional information in this answer : Multiple parameter closure argument type not inferred
Strictly speaking, the example you gave is not really curried, it just has multiple argument lists. It just happens that multiple argument list Scala functions look a lot like curried functions in many situations. However, when you call a multiple argument list function but don't fill in one or more argument lists, it's really an example of partial application, not currying. Calling a multiple argument list with all its arguments is just one function call, not one per argument list.
There are two use cases where multiple argument list functions are helpful. The first is the case of implicit parameters, since all implicit parameters have to be in their own argument list separate from any explicit parameters. The second use case is functions that accept other functions as parameters, since if a parameter that is a function is in its own argument list, you can leave off the parentheses and just use braces, making the function call look like some sort of control structure.
Other than that, the difference is purely cosmetic.