Why does Scala apply thunks automatically, sometimes?

Posted by Anonymouse on Stack Overflow See other posts from Stack Overflow or by Anonymouse
Published on 2010-05-29T09:56:54Z Indexed on 2010/05/29 10:02 UTC
Read the original article Hit count: 282

Filed under:
|

At just after 2:40 in ShadowofCatron's Scala Tutorial 3 video, it's pointed out that the parentheses following the name of a thunk are optional. "Buh?" said my functional programming brain, since the value of a function and the value it evaluates to when applied are completely different things.

So I wrote the following to try this out. My thought process is described in the comments.

object Main {

    var counter: Int = 10
    def f(): Int = { counter = counter + 1; counter }

    def runThunk(t: () => Int): Int = { t() }

    def main(args: Array[String]): Unit = {
        val a = f()     // I expect this to mean "apply f to no args"
        println(a)      // and apparently it does

        val b = f       // I expect this to mean "the value f", a function value
        println(b)      // but it's the value it evaluates to when applied to no args
        println(b)      // and the evaluation happens immediately, not in the call

        runThunk(b)     // This is an error: it's not println doing something funny
        runThunk(f)     // Not an error: seems to be val doing something funny
    }

}

 

To be clear about the problem, this Scheme program (and the console dump which follows) shows what I expected the Scala program to do.

(define counter (list 10))
(define f (lambda ()
            (set-car! counter (+ (car counter) 1))
            (car counter)))

(define runThunk (lambda (t) (t)))

(define main (lambda args
               (let ((a (f))
                     (b f))
                 (display a) (newline)
                 (display b) (newline)
                 (display b) (newline)
                 (runThunk b)
                 (runThunk f))))

> (main)
11
#<procedure:f>
#<procedure:f>
13

 

After coming to this site to ask about this, I came across this answer which told me how to fix the above Scala program:

    val b = f _     // Hey Scala, I mean f, not f()

But the underscore 'hint' is only needed sometimes. When I call runThunk(f), no hint is required. But when I 'alias' f to b with a val then apply it, it doesn't work: the evaluation happens in the val; and even lazy val works this way, so it's not the point of evaluation causing this behaviour.

 

That all leaves me with the question:

Why does Scala sometimes automatically apply thunks when evaluating them?

Is it, as I suspect, type inference? And if so, shouldn't a type system stay out of the language's semantics?

Is this a good idea? Do Scala programmers apply thunks rather than refer to their values so much more often that making the parens optional is better overall?


Examples written using Scala 2.8.0RC3, DrScheme 4.0.1 in R5RS.

© Stack Overflow or respective owner

Related posts about beginner

Related posts about scala