The*_*aul 22 functional-programming scala immutability lazy-evaluation
这只是"我想知道......"问题中的一个.
Scala具有不可变数据结构和(可选)惰性值等.
Scala程序与完全纯粹(在函数编程意义上)和完全懒惰(或Ingo指出,它是否足够非严格)的程序有多接近?哪些价值观不可避免地变得多变,什么评价不可避免地贪婪?
axe*_*l22 15
关于延迟 - 当前,将参数传递给方法默认是严格的:
def square(a: Int) = a * a
Run Code Online (Sandbox Code Playgroud)
但是你使用call-by-name参数:
def square(a: =>Int) = a * a
Run Code Online (Sandbox Code Playgroud)
但这并不是懒惰的,因为它只在需要时计算一次值:
scala> square({println("calculating");5})
calculating
calculating
res0: Int = 25
Run Code Online (Sandbox Code Playgroud)
添加惰性方法参数已经有了一些工作,但尚未集成(以下声明"calculating"只能从上面打印一次):
def square(lazy a: Int) = a * a
Run Code Online (Sandbox Code Playgroud)
这是一个缺少的部分,虽然你可以使用本地懒惰的val来模拟它:
def square(ap: =>Int) = {
lazy val a = ap
a * a
}
Run Code Online (Sandbox Code Playgroud)
关于可变性 - 没有什么能阻止你编写不可变数据结构并避免变异.您也可以在Java或C中执行此操作.实际上,一些不可变数据结构依赖于惰性原语来实现更好的复杂边界,但是懒惰原语也可以用其他语言模拟 - 以额外的语法和样板为代价.
您总是可以在Scala中编写不可变数据结构,延迟计算和完全纯的程序.问题是Scala编程模型也允许编写非纯程序,因此类型检查器不能总是推断程序的某些属性(例如纯度),它可以推断出编程模型更具限制性.
例如,在具有纯表达式的语言中,a * a上面(a: =>Int)中的按名称调用定义可以被优化为a仅评估一次,而不管按名称调用语义.如果语言允许副作用,那么这种优化并不总是适用.
Tom*_*ett 14
Scala可以像你喜欢的那样纯粹和懒惰,但是a)编译器不会让你对纯度保持诚实,b)它需要一些额外的工作来使它变得懒惰.对此没什么太深刻的了; 如果你真的想要,你甚至可以编写懒惰和纯Java代码(如果你敢,请看这里 ;在Java中实现懒惰需要大量嵌套的匿名内部类).
Haskell通过类型系统跟踪杂质,而Scala选择不采用这种方式,当你从一开始就没有把它作为一个目标时(以及当它与一种完全不纯的语言的互操作性时)很难解决这类问题像Java 是该语言的主要目标).
也就是说,有些人认为在Scala的类型系统中记录效果是可能的,也是值得的.但我认为Scala中的纯度最好被视为自律问题,并且您必须对所谓的第三方代码的纯度持怀疑态度.
Haskell默认是懒惰的,但是可以通过代码中添加一些注释来更严格... Scala是相反的:默认情况下是strict,但是使用lazy关键字和by-name参数可以使它像你喜欢的那样懒惰.