为什么Scala会自动应用thunk,有时候呢? [英] Why does Scala apply thunks automatically, sometimes?

查看:121
本文介绍了为什么Scala会自动应用thunk,有时候呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ShadowofCatron <2 href =http: //www.youtube.com/watch?v=R3gh9jIIbMErel =nofollow noreferrer> Scala Tutorial 3 video ,它指出后面的括号括起来 thunk 是可选 。 寮步?说我的函数式编程大脑,因为一个函数的值和它在应用时所评估的值是完全不同的东西。

所以我写了以下内容来试验。

  object主体{

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

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

def main(args:Array [String]):Unit = {
val a = f()//我期望这个意思是apply f to no args
println(a)//显然它确实是

val b = f //我希望这意味着值f,一个函数值
println(b)//但它是它在应用于无参数时所评估的值
println(b)//和应用程序立即发生,而不是在调用

runThunk(b)//这是一个错误:它不是println做一些有趣的事
runThunk(f)//不是一个错误:似乎为val做一些有趣的事情


$ b code $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ;

为了清楚这个问题,这个Scheme程序(以及后面的控制台转储)显示了我期望Scala程序的功能。

 (define counter(list 10))
(define f(la mbda()
(set-car!计数器(+(汽车计数器)1))
(汽车计数器)))

(定义runThunk(lambda(t)(t)))

定义main(lambda参数
(let((a(f))
(bf))
(显示a)(换行符)
(显示b)(换行符)
(display b)(newline)
(runThunk b)
(runThunk f))))

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

 



在来到这个网站询问这个问题后,我碰到

  val b = f _145486>这个答案告诉我如何修正上面的Scala程序: //嘿Scala,我的意思是f,而不是f()

但下划线'提示'只是需要有时。当我调用 runThunk(f)时,不需要提示。但是,当我使用 val 别名'f到b然后应用它时,它不起作用:应用程序发生在 val ;甚至是 lazy val 都是这样工作的,所以它不是导致这种行为的评估点。

 



这些都给我留下了一个问题:



为什么Scala有时 >在评估它们时自动应用thunk?



是否如我猜想的那样输入推理?如果是这样,不应该一个类型系统超出语言的语义吗?



这是个好主意吗? Scala程序员是否应用thunks而不是引用它们的值更经常地使得parens可选更好?




在R5RS中使用Scala 2.8.0RC3,DrScheme 4.0.1编写的例子。 解决方案

这里:


Buh?表示我的函数式编程
brain,因为函数
的值和值它的计算结果是
的应用是完全不同的
的东西。

是的,但是你没有声明任何函数。

  def f():Int = {counter = counter + 1; counter} 
f
方法,它有一个空的 参数列表,并返回 Int 。一个方法不是一个函数 - 它没有一个值,从来没有,最好的办法是得到一个 Method 通过反射实例,即n (b)

  val b = f _ //嘿Scala,我的意思是f,而不是f() 

那么, f _ 是什么意思?如果 f 是一个函数,它将意味着函数本身,授予,但在这里不是这种情况。它的真正含义是这样的:

  val b =()=> f()

换句话说, f _ 是通过方法调用的闭包。通过函数实现闭包。



最后,为什么在Scala中可选的空参数列表?因为虽然Scala允许声明,例如 def f = 5 ,但Java没有。 Java中的所有方法至少需要一个空的参数列表。在Scala风格中,有很多这样的方法不会有任何参数(例如,长度大小 )。因此,为了让代码看起来更加统一,Scala使它们成为可选。


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 application 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 application 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.

解决方案

The problem is here:

Buh?" said my functional programming brain, since the value of a function and the value it evaluates to when applied are completely different things.

Yes, but you did not declare any function.

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

You declared a method called f which has one empty parameter list, and returns Int. A method is not a function -- it does not have a value. Never, ever. The best you can do is get a Method instance through reflection, which is not really the same thing at all.

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

So, what does f _ means? If f was a function, it would mean the function itself, granted, but this is not the case here. What it really means is this:

val b = () => f()

In other words, f _ is a closure over a method call. And closures are implemented through functions.

Finally, why are empty parameter lists optional in Scala? Because while Scala allows declarations such as def f = 5, Java does not. All methods in Java require at least an empty parameter list. And there are many such methods which, in Scala style, would not have any parameters (for example, length and size). So, to make the code look more uniform with regards to empty parameter list, Scala makes them optional.

这篇关于为什么Scala会自动应用thunk,有时候呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆