Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between () => Int and Unit => Int? What on earth is the type of "()" in Scala?

Tags:

scala

I think I still have not fully understood what type () represent during function definition. So I can't come up concrete example of each case: () => Int; Unit=> Int.

Can someone give me an easy example of function literal with type () => Int and type Unit=>Int respectively? After that, I think I can learn what () is exactly is.

Thanks

*EDIT: * destin says they are same. But the following test seems to indicate otherwise: () can't be used in place expecting Unit.

scala> def inCase[A] ( b :Boolean, ifTrue : Unit => A, ifFalse : Unit => A ) : A  = 
 |     b match {
 |         case True => ifTrue()
 |         case _ => ifFalse()
 |     }

 inCase: [A](b: Boolean, ifTrue: Unit => A, ifFalse: Unit => A)A


scala> inCase( True,  () => 1,  () => -1 )
 <console>:11: error: type mismatch;
 found   : () => Int
  required: Unit => ?
          inCase( True,  () => 1,  () => -1 )
like image 279
chen Avatar asked May 29 '12 01:05

chen


2 Answers

() in a function type is not a type at all, nor is it a value. () => is simply syntax to indicate a function that takes zero arguments. See the BNF notation in section 3.2.9 of the Scala specification.

When you see (Type1, Type2, Type3) => Type4, the () surrounds all of the argument types that the function takes. (Type1, Type2, Type3) is not a tuple type here -- the parentheses are just syntax. So when you see () => Type4, you have an argument list that takes zero parameters. Single argument functions are special, in that you can omit the parentheses.

Functions with no arguments, specified without the (), simply => Type4 are by-name parameters (which look like values, but are implemented as functions that get called implicitly when you try to evaluate their value.) They're defined in section 4.6.1 of the spec.

Parentheses can mean a bunch of other things in other contexts.

  • Parentheses in a function type declaration anywhere other than right before the => indicate a tuple type, and these can't be empty. (Section 3.2.5)
  • Empty parentheses () are the return value of functions whose return type is Unit. (Section 12.2.3) This actually becomes a real value in certain contexts, for example println(println("foo")) will print

    foo                 <--- the argument to the inner println
    ()                  <--- the argument to the outer println
    
  • Parentheses are also syntax for function arguments when you make a function call, something that you're probably already aware of. These can be empty. They're defined in section 6.6 of the spec.

  • Parentheses are also syntax for function arguments when you define a method using def. These are described in section 4.6 of the spec.
  • Parentheses are also the syntax for creating tuple values (Section 6.9). If they're not empty, you get a TupleN where N is the number of values inside of the parentheses. If they are empty, the type of this expression is Unit. (Sections 6.9, 12.2.3)
like image 127
Ken Bloom Avatar answered Sep 26 '22 12:09

Ken Bloom


I changed your example, to have both notations (and to use the more popular Boolean):

def inCase[A] (b:Boolean, ifTrue: ()=> A, ifFalse: Unit => A): A = b match {
  case true => ifTrue ()
  case _    => ifFalse ()
}

inCase (true, () => 1,  (Unit) => -1)

Then I have to use the same notation on the calling site.

like image 27
user unknown Avatar answered Sep 23 '22 12:09

user unknown