This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Understanding Functional Arguments

7 replies
SSP
Joined: 2012-01-27,
User offline. Last seen 42 years 45 weeks ago.

Hi,

I am relatively new to scala, and I am not understanding few concepts
related to function arguments. Please take a look at the code below.
The behavior is the same for all three function call- Calls f1, then
f2 then pm. I am not understanding why I cant use function _ in the
code (I have put a comment). What is the difference between f: =>
String and f:() => String? When to use the specific syntax?

object Tester {

def main(args:Array[String]){
def pm = {
println("In PM")
"PM"
}

val a = A(1, pm _)
a.f1() //Call 1

//Call 2
f1(1){ //Cant use pm _ here, why?
pm
}

//Call 3
f1Dash(1, pm) //Cant use pm _ here, why?
}

def f1Dash(i:Int, f: => String) = {
println("In F1Dash, calling F2")
f2(f)
}

def f1(i:Int)( f: => String) = {
println("In F1, calling F2")
f2(f)
}

def f2(f: => String){
println("In F2, calling f")
f
}
}

case class A(i:Int, f:() => String){
def f1() = {
println("In F1, calling F2")
f2(f())
}

def f2(f: => String){
println("In F2, calling f")
f
}
}

Thanks,
Shreyas Purohit

Alex Repain
Joined: 2010-07-27,
User offline. Last seen 1 year 31 weeks ago.
Re: Understanding Functional Arguments
When defining the class A, your argument f has type '() => String', which is a function type. In the definition of f1 and f1Dash, the type of the argument f is '=> String', which is a syntactic structure for "something that can be evaluated to a String, but will not be evaluated before calling f1 on it'. It's called "by-name" argument passing.

when you call f1(1){ pm } and f1Dash(1, pm)  :
- f1 and f1Dash expect a String, and will take it as a by-name argument. It does not expect a function.
- "pm" represents a call to the function pm, which evaluates to a String. Passed as a by-name argument, they won't be evaluated before calling f1 or f1Dash, but the type is corresponding nonetheless.
- you can't pass "pm _" because this syntax is used to indicate a partial function application. Here pm expects no argument, so "pm _" simply types as a function, of type () => String.

when you call A(1, pm _) :
- A expects a function as 2nd argument
- "pm _" is of type () => String, as expected by your class A.
- "pm" wouldn't fit, because it types as a String

Because Scala allows 0-argument function to be called without parenthesis ( f instead of f() ), "f _" is the way to specify you pass the function itself, and not its evaluation result.

To state the difference by a simple example, in the Scala REPL :

> def f = "3"
f: java.lang.String
> f
res0: java.lang.String = 3
> f _
res1: () => java.lang.String =

> def g(f: => String) = f
g: (f: => String)String

> g(f)
res2: String = 3

> g(f _)
error: type mismatch; found : () => java.lang.String required: String g(f _) ^


2012/1/27 SSP <Shreyas.Purohit@sabre.com>
Hi,

I am relatively new to scala, and I am not understanding few concepts
related to function arguments. Please take a look at the code below.
The behavior is the same for all three function call- Calls f1, then
f2 then pm. I am not understanding why I cant use function _ in the
code (I have put a comment). What is the difference between f: =>
String and f:() => String? When to use the specific syntax?

object Tester {

       def main(args:Array[String]){
         def pm = {
           println("In PM")
           "PM"
         }

         val a = A(1, pm _)
         a.f1() //Call 1

         //Call 2
         f1(1){  //Cant use pm _ here, why?
           pm
         }

         //Call 3
         f1Dash(1, pm) //Cant use pm _ here, why?
       }

 def f1Dash(i:Int, f: => String) = {
   println("In F1Dash, calling F2")
       f2(f)
 }

 def f1(i:Int)( f: => String) = {
   println("In F1, calling F2")
       f2(f)
 }

 def f2(f: => String){
   println("In F2, calling f")
   f
 }
}

case class A(i:Int, f:() => String){
 def f1() = {
         println("In F1, calling F2")
         f2(f())
 }

 def f2(f: => String){
   println("In F2, calling f")
   f
 }
}

Thanks,
Shreyas Purohit

Alex Repain
Joined: 2010-07-27,
User offline. Last seen 1 year 31 weeks ago.
Re: Understanding Functional Arguments


2012/1/28 Alex Repain <alex.repain@gmail.com>
When defining the class A, your argument f has type '() => String', which is a function type. In the definition of f1 and f1Dash, the type of the argument f is '=> String', which is a syntactic structure for "something that can be evaluated to a String, but will not be evaluated before calling f1 on it'. It's called "by-name" argument passing.

when you call f1(1){ pm } and f1Dash(1, pm)  :
- f1 and f1Dash expect a String, and will take it as a by-name argument. It does not expect a function.
- "pm" represents a call to the function pm, which evaluates to a String. Passed as a by-name argument, they won't be evaluated before calling f1 or f1Dash, but the type is corresponding nonetheless.
- you can't pass "pm _" because this syntax is used to indicate a partial function application. Here pm expects no argument, so "pm _" simply types as a function, of type () => String.

when you call A(1, pm _) :
- A expects a function as 2nd argument
- "pm _" is of type () => String, as expected by your class A.
- "pm" wouldn't fit, because it types as a String

Because Scala allows 0-argument function to be called without parenthesis ( f instead of f() ), "f _" is the way to specify you pass the function itself, and not its evaluation result.

And by the way, this is the syntax for functions that have 1 or more arguments, too. Given the above function g, in he Scala REPL :

 
> g
error: missing arguments for method g in object $iw; follow this method with `_' if you want to treat it as a partially applied function g // hello ^
> g _ // hello
res5: (=> String) => String =

To state the difference by a simple example, in the Scala REPL :

> def f = "3"
f: java.lang.String
> f
res0: java.lang.String = 3
> f _
res1: () => java.lang.String =

> def g(f: => String) = f
g: (f: => String)String

> g(f)
res2: String = 3

> g(f _)
error: type mismatch; found : () => java.lang.String required: String g(f _) ^


2012/1/27 SSP <Shreyas.Purohit@sabre.com>
Hi,

I am relatively new to scala, and I am not understanding few concepts
related to function arguments. Please take a look at the code below.
The behavior is the same for all three function call- Calls f1, then
f2 then pm. I am not understanding why I cant use function _ in the
code (I have put a comment). What is the difference between f: =>
String and f:() => String? When to use the specific syntax?

object Tester {

       def main(args:Array[String]){
         def pm = {
           println("In PM")
           "PM"
         }

         val a = A(1, pm _)
         a.f1() //Call 1

         //Call 2
         f1(1){  //Cant use pm _ here, why?
           pm
         }

         //Call 3
         f1Dash(1, pm) //Cant use pm _ here, why?
       }

 def f1Dash(i:Int, f: => String) = {
   println("In F1Dash, calling F2")
       f2(f)
 }

 def f1(i:Int)( f: => String) = {
   println("In F1, calling F2")
       f2(f)
 }

 def f2(f: => String){
   println("In F2, calling f")
   f
 }
}

case class A(i:Int, f:() => String){
 def f1() = {
         println("In F1, calling F2")
         f2(f())
 }

 def f2(f: => String){
   println("In F2, calling f")
   f
 }
}

Thanks,
Shreyas Purohit


SSP
Joined: 2012-01-27,
User offline. Last seen 42 years 45 weeks ago.
RE: Understanding Functional Arguments

Alex,

 

Thanks a lot for the wonderful explanation. I understand. But, just to be clear, here the confusing part is that “by-name” argument is not really evaluated till it is invoked. In a way, it is a function that is waiting to be invoked to do some work. It looks like the only difference is that => String is not the same type of function as () => String. What do you think?

 

Thanks,

Shreyas Purohit

 

 

From: Alex Repain [mailto:alex.repain@gmail.com]
Sent: Friday, January 27, 2012 6:23 PM
To: Purohit, Shreyas
Cc: scala-user
Subject: Re: [scala-user] Understanding Functional Arguments

 

When defining the class A, your argument f has type '() => String', which is a function type. In the definition of f1 and f1Dash, the type of the argument f is '=> String', which is a syntactic structure for "something that can be evaluated to a String, but will not be evaluated before calling f1 on it'. It's called "by-name" argument passing.

when you call f1(1){ pm } and f1Dash(1, pm)  :
- f1 and f1Dash expect a String, and will take it as a by-name argument. It does not expect a function.
- "pm" represents a call to the function pm, which evaluates to a String. Passed as a by-name argument, they won't be evaluated before calling f1 or f1Dash, but the type is corresponding nonetheless.
- you can't pass "pm _" because this syntax is used to indicate a partial function application. Here pm expects no argument, so "pm _" simply types as a function, of type () => String.

when you call A(1, pm _) :
- A expects a function as 2nd argument
- "pm _" is of type () => String, as expected by your class A.
- "pm" wouldn't fit, because it types as a String

Because Scala allows 0-argument function to be called without parenthesis ( f instead of f() ), "f _" is the way to specify you pass the function itself, and not its evaluation result.

To state the difference by a simple example, in the Scala REPL :

> def f = "3"
f: java.lang.String
> f
res0: java.lang.String = 3
> f _
res1: () => java.lang.String =

> def g(f: => String) = f
g: (f: => String)String

> g(f)
res2: String = 3

> g(f _)
error: type mismatch;
 found   : () => java.lang.String
 required: String
       g(f _)
         ^
 

 

2012/1/27 SSP <Shreyas.Purohit@sabre.com>

Hi,

I am relatively new to scala, and I am not understanding few concepts
related to function arguments. Please take a look at the code below.
The behavior is the same for all three function call- Calls f1, then
f2 then pm. I am not understanding why I cant use function _ in the
code (I have put a comment). What is the difference between f: =>
String and f:() => String? When to use the specific syntax?

object Tester {

       def main(args:Array[String]){
         def pm = {
           println("In PM")
           "PM"
         }

         val a = A(1, pm _)
         a.f1() //Call 1

         //Call 2
         f1(1){  //Cant use pm _ here, why?
           pm
         }

         //Call 3
         f1Dash(1, pm) //Cant use pm _ here, why?
       }

 def f1Dash(i:Int, f: => String) = {
   println("In F1Dash, calling F2")
       f2(f)
 }

 def f1(i:Int)( f: => String) = {
   println("In F1, calling F2")
       f2(f)
 }

 def f2(f: => String){
   println("In F2, calling f")
   f
 }
}

case class A(i:Int, f:() => String){
 def f1() = {
         println("In F1, calling F2")
         f2(f())
 }

 def f2(f: => String){
   println("In F2, calling f")
   f
 }
}

Thanks,
Shreyas Purohit

 

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Understanding Functional Arguments
On Fri, Jan 27, 2012 at 8:32 PM, Purohit, Shreyas <Shreyas.Purohit@sabre.com> wrote:

Alex,

 

Thanks a lot for the wonderful explanation. I understand. But, just to be clear, here the confusing part is that “by-name” argument is not really evaluated till it is invoked. In a way, it is a function that is waiting to be invoked to do some work. It looks like the only difference is that => String is not the same type of function as () => String. What do you think?


Indeed.  It makes a syntactic difference to the compiler, but it's implemented using Function0 (i.e. () => A).  If you were calling it from Java, you wouldn't be able to tell the difference between x: => A and x: () => A (for any A).

  --Rex

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Understanding Functional Arguments

On Fri, Jan 27, 2012 at 23:32, Purohit, Shreyas
wrote:
> Alex,
>
>
>
> Thanks a lot for the wonderful explanation. I understand. But, just to be
> clear, here the confusing part is that “by-name” argument is not really
> evaluated till it is invoked. In a way, it is a function that is waiting to
> be invoked to do some work. It looks like the only difference is that =>
> String is not the same type of function as () => String. What do you think?

You are confusing what by-name is with how it is implemented. => T
means pass T by name, while T means pass T by value. () => String is a
Function0[String], while String is just that: String.

SSP
Joined: 2012-01-27,
User offline. Last seen 42 years 45 weeks ago.
RE: Understanding Functional Arguments

Thanks Rex. Its clear now.

-Shreyas Purohit

----------------------------------------------------------------------------------------------------
________________________________________
From: Rex Kerr [ichoran@gmail.com]
Sent: Saturday, January 28, 2012 3:34 AM
To: Purohit, Shreyas
Cc: Alex Repain; scala-user
Subject: Re: [scala-user] Understanding Functional Arguments

On Fri, Jan 27, 2012 at 8:32 PM, Purohit, Shreyas > wrote:
Alex,

Thanks a lot for the wonderful explanation. I understand. But, just to be clear, here the confusing part is that “by-name” argument is not really evaluated till it is invoked. In a way, it is a function that is waiting to be invoked to do some work. It looks like the only difference is that => String is not the same type of function as () => String. What do you think?

Indeed. It makes a syntactic difference to the compiler, but it's implemented using Function0 (i.e. () => A). If you were calling it from Java, you wouldn't be able to tell the difference between x: => A and x: () => A (for any A).

--Rex

SSP
Joined: 2012-01-27,
User offline. Last seen 42 years 45 weeks ago.
RE: Understanding Functional Arguments

Daniel,
Thanks for the explanation. I was trying to understand w.r.t usage, just bumped into how it is implemented while trying to understand the difference! It very clear now.

Thank you all for making me understand.

-Shreyas Purohit

------------------------------------------------------------------------------------------------------
________________________________________
From: Daniel Sobral [dcsobral@gmail.com]
Sent: Saturday, January 28, 2012 7:52 AM
To: Purohit, Shreyas
Cc: Alex Repain; scala-user
Subject: Re: [scala-user] Understanding Functional Arguments

On Fri, Jan 27, 2012 at 23:32, Purohit, Shreyas
wrote:
> Alex,
>
>
>
> Thanks a lot for the wonderful explanation. I understand. But, just to be
> clear, here the confusing part is that “by-name” argument is not really
> evaluated till it is invoked. In a way, it is a function that is waiting to
> be invoked to do some work. It looks like the only difference is that =>
> String is not the same type of function as () => String. What do you think?

You are confusing what by-name is with how it is implemented. => T
means pass T by name, while T means pass T by value. () => String is a
Function0[String], while String is just that: String.

--
Daniel C. Sobral

I travel to the future all the time.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland