首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Scala中调用名称,在Haskell中调用惰性评估?

在Scala中调用名称,在Haskell中调用惰性评估?
EN

Stack Overflow用户
提问于 2017-01-22 00:14:19
回答 2查看 1.6K关注 0票数 11

Haskell的懒惰评估将永远不会比急切的评估采取更多的评估步骤。

另一方面,Scala的逐名评估可能需要比按值调用更多的评估步骤(如果短路的好处被重复计算的成本所抵消)。

我以为按名字叫大致相当于懒散的评估。那为什么时间保证会有这样的差别呢?

我猜想Haskell语言可能指定在评估过程中必须使用回忆录;但是在这种情况下,Scala为什么不这样做呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-22 00:45:24

评价战略的名称有一定的广泛性,但大致可以归结为:

  • 调用名称为,一个参数几乎被替换到函数体中,不管函数是以什么形式调用的(未计算的)。这意味着它可能需要在身体中进行多次评估。 在Scala中,您将以下内容写成: scala> def (x:=> Int):Int =x+x scala> f({ println(“x:=>”);1 }) 在Haskell中,您没有以这样的方式构建,但是始终可以将按名称调用的值表示为() -> a类型的函数。但是,由于引用的透明性,这有点模糊--您将无法像使用Scala那样测试它(编译器可能会优化调用的"by name“部分)。
  • 按需要呼叫(懒惰.在调用函数时,不计算参数,而是需要在第一次调用时计算参数。在那一刻,它也被缓存。然后,每当再次需要参数时,就会查找缓存的值。 在Scala中,不声明函数参数为惰性,而是声明为懒惰: scala>惰性x: Int ={println(“计算”);1} scala> x+x求值2 在Haskell中,默认情况下所有函数都是这样工作的。
  • 按值调用(几乎每种语言所做的)参数在调用函数时进行计算,即使函数没有使用这些参数。 在Scala中,默认情况下这就是函数的工作方式。 scala> def (x: Int):Int =x+x scala> f({ println(“计算”);1 })求值2 在Haskell中,您可以在函数参数上使用bang模式强制这种行为: ghci> :{ ghci> f ::Int -> Int ghci> f !x =x ghci> :}

那么,如果按需要调用(懒散)所做的评估与其他任何一种策略一样多或更少,那么为什么还要使用其他方法呢?

除非您具有引用透明度,否则懒散的评估很难推理,因为您需要准确地确定什么时候对懒惰值进行了计算。由于Scala是为与Java互操作而构建的,所以它需要支持命令式的、副作用的编程.因此,在许多情况下,在Scala中使用lazy并不是一个好主意。

此外,lazy还有性能开销:您需要额外的间接检查值是否已经评估过。在Scala中,这转化为一组更多的对象,这给垃圾收集器带来了更大的压力。

最后,在有些情况下,延迟计算会留下“空间”漏洞。例如,在Haskell中,将一大串数字从右边叠加在一起是个坏主意,因为Haskell会在对(+)进行评估之前建立一系列庞大的懒散调用(实际上,您只需要它有一个累加器。即使在简单的上下文中,空间问题的一个著名例子是foldl'

票数 13
EN

Stack Overflow用户

发布于 2017-01-22 08:02:09

这可能很有用,也不太适合评论。

您可以在Scala中编写一个函数,它的行为类似于Haskell的逐需要调用(用于参数),方法是按名称调用参数,并在函数开始时懒洋洋地对它们进行评估:

代码语言:javascript
复制
def foo(x: => Int) = {
  lazy val _x = x
  // make sure you only use _x below, not x
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41785985

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档