tags:

views:

216

answers:

3
 def foo(x:Int, f:Unit=>Int) = println(f())

foo(2, {Unit => 3+4}

//case1
def loop:Int = 7
foo(2, loop) //does not compile

changing loop to 
//case 2
def loop():Int = 7
foo(2, loop) // does not compile

changing loop to
//case 3
def loop(x:Unit): Int = 7 //changing according to Don's Comments
foo(2,loop) // compiles and works fine

should'nt case 1 and case 2 also work? why are they not working?

defining foo as

def foo(x:Int, y:()=>Int)

then case 2 works but not case 1.

Arent they all supposed to work, defining the functions either way.

//also i think ()=>Int in foo is a bad style, y:=>Int does not work, comments??

+1  A: 

()=>Int is Function0[Int] while Unit=>Int is Function1[Unit,Int]

scala> val function0: () => Int = () => 5
function0: () => Int = <function0>

scala> val function1: Unit => Int = u => 5
function1: (Unit) => Int = <function1>

scala> function0()
res0: Int = 5

scala> function1("anything")
res1: Int = 5

scala> function1(100)
res2: Int = 5

scala>

Also note that () is an object of Unit

scala> function1(())
res11: Int = 5

scala> function1 ()
res12: Int = 5

scala> function1()
res13: Int = 5

scala> val unit = ()
unit: Unit = ()


scala> function1(unit)
res15: Int = 5

scala> function1 apply unit
res16: Int = 5

scala>
Eastsun
scala> val function1: Unit => Int = Unit => 5Note that in this line, the last "Unit" is not a type identifier, but just a name for the parameter (you could change it to "x" for example).
Dimitris Andreou
@Dimitris Andreou: Yes, you are right.
Eastsun
+12  A: 

Scala distinguishes between the following things:

  • Functions/methods with no parameter lists ("by-name parameter" if a function)
  • Functions with one empty parameter list
  • Functions with one parameter of type Unit

None of these are equivalent, although as a convenience Scala allows you to elide empty parameter lists. (Incidentally, two empty parameter lists are also not the same.)

So, even though Unit is written (), this is not the same as the function argument parens () for a function or method. Instead, think of () as a Tuple0.

So, if you say f: Unit => Int, what you mean is "f takes one parameter, but it's a really boring parameter because it is Unit, which must always be the same boring Tuple0 value ()". What you're writing is really short for f: (Unit) => Int.

If you say f: () => Int, then you mean that "f takes no parameters and produces an Int".

If you say f: => Int, then you mean that "delay the execution of whatever statement produces an Int value until we use it in this code (and re-evaluate it each time)". Functionally, this ends up being basically the same as f: () => Int (and internally is converted into the same Function0 class), but it has a different usage, presumably to allow for a more compact form of closures (you always omit the => in the calling code).

Rex Kerr
So if I have a function def loop() = 7It really makes no sense for me to insert unit, as indef loop(x:Unit) = 7 , if I want to pass it to another function like foo above.
scout
@Scout: There's no reason to add a superfluous `Unit` in that case. It is useful for abstraction. Suppose you have a composition function: `def comp[A,B,C](f: A=>B, g: B=>C, a: A) = g(f(a))` and you try to pass it a `f` that doesn't return a value. Now what do you do? Well, it turns out that Scala always _does_ return something--at least `()` (the only possible value of type `Unit`). So now you can write a `g` that takes an input of type `Unit` and use the general composition function above. But for most situations, just use `def f() = ...` or `def f = ...`.
Rex Kerr
+2  A: 

In case 1 and 2 above, the return value of loop rather than loop itself is type checked for the second argument to foo and fails: Int != Unit => Int

The change to loop has a typo.

Don Mackenzie