Scala有多纯粹和懒惰?

时间:2011-09-26 08:47:12

标签: scala functional-programming immutability lazy-evaluation

这只是其中一个“我想知道......”的问题。

Scala具有不可变数据结构和(可选)惰性值等。

Scala程序与完全纯粹(在函数编程意义上)和完全懒惰(或Ingo指出,它是否足够非严格)的程序有多接近?什么价值观不可避免地变得可变,什么评价不可避免地贪婪?

3 个答案:

答案 0 :(得分:15)

关于延迟 - 目前,将参数传递给方法默认为严格:

def square(a: Int) = a * a

但您使用按名称调用参数:

def square(a: =>Int) = a * a

但这并不是懒惰的,因为它只在需要时计算

scala> square({println("calculating");5})
calculating
calculating
res0: Int = 25

添加 lazy 方法参数已有一些工作,但尚未集成(以下声明只能从上面打印"calculating"一次):

def square(lazy a: Int) = a * a

这是一个缺失的部分,尽管你可以使用本地懒惰的val模拟它:

def square(ap: =>Int) = {
  lazy val a = ap
  a * a
}

关于可变性 - 没有什么可以阻止你编写不可变数据结构并避免变异。您也可以在Java或C中执行此操作。实际上,some immutable data structures依赖于惰性原语来实现更好的复杂边界,但是懒惰的原语也可以用其他语言模拟 - 以额外的语法和样板为代价。

您总是可以在Scala中编写不可变数据结构,延迟计算和完全纯粹的程序。问题是Scala编程模型也允许编写非纯程序,因此类型检查器不能总是推断程序的某些属性(例如纯度),它可以推断出编程模型的限制性更强。

例如,在具有纯表达式的语言中,上述(a * a)按名称定义中的a: =>Int可以优化,仅评估a一次,无论按名称调用语义。如果语言允许副作用,那么这种优化并不总是适用。

答案 1 :(得分:14)

Scala可以像你想的那样纯粹和懒惰,但是a)编译器不会让你对纯度保持诚实,b)它需要一些额外的工作来使它变得懒惰。对此没什么太深刻的了;你甚至可以编写懒惰和纯粹的 Java 代码(如果你敢的话,请参阅here;在Java中实现懒惰需要大量嵌套的匿名内部类)。

纯度

Haskell通过类型系统跟踪杂质,而Scala选择不采用这种方式,当你从一开始就没有把它作为一个目标时(以及当它的互操作性时)很难解决这类问题。完全不纯的语言,如Java 语言的主要目标)。

那就是说some believe,在Scala的类型系统中记录效果是可能的,也是值得的。但我认为Scala中的纯度最好被视为一种自律问题,你必须对所谓的第三方代码的纯度持怀疑态度。

懒惰

Haskell在默认情况下是懒惰的,但是可以通过代码中添加一些注释来更严格... Scala是相反的:默认情况下是严格的,但是使用lazy关键字和by-name参数可以使其成为你喜欢懒惰。

答案 2 :(得分:3)

随意保持不变。另一方面,没有副作用跟踪,因此您无法强制执行或验证它。

至于非严格性,这是交易......首先,如果你选择完全不严格,你将放弃所有Scala的课程。即使Scalaz在很大程度上也不是非严格的。如果你愿意自己构建一切,你可以使你的方法不严格,你的价值观也很懒惰。

接下来,我想知道隐含参数是否可以是非严格的,或者将它们设置为非严格的后果是什么。我没有看到问题,但我错了。

但是,最有问题的是,函数参数是严格的,闭包参数也是如此。

因此,虽然理论上可以完全不严格,但这将非常不方便。