Scala 能有多纯粹和懒惰?

发布于 2024-12-06 15:18:33 字数 168 浏览 6 评论 0原文

这只是“我想知道……”的问题之一。

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

程序与完全纯粹(在函数式编程意义上)和完全惰性的程序有多接近(或者正如 Ingo 指出的那样,它是否可以足够不严格) )?哪些价值观不可避免地是可变的,哪些评估不可避免地是贪婪的?

This is just one of those "I was wondering..." questions.

Scala has immutable data structures and (optional) lazy vals etc.

How close can a Scala program be to one that is fully pure (in a functional programming sense) and fully lazy (or as Ingo points out, can it be sufficiently non-strict)? What values are unavoidably mutable and what evaluation unavoidably greedy?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

权谋诡计 2024-12-13 15:18:33

关于惰性 - 目前,将参数传递给方法默认是严格的:

def square(a: Int) = a * a

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

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

但这在它仅计算值的意义上并不是惰性的需要时一次:

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

添加惰性方法参数方面已经做了一些工作,但尚未集成(下面的声明应打印“计算”上面只有一次):

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

这是缺少的一块,尽管您可以使用本地惰性 val 来模拟它:

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

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

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

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

Regarding lazyness - currently, passing a parameter to a method is by default strict:

def square(a: Int) = a * a

but you use call-by-name parameters:

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

but this is not lazy in the sense that it computes the value only once when needed:

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

There's been some work into adding lazy method parameters, but it hasn't been integrated yet (the below declaration should print "calculating" from above only once):

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

This is one piece that is missing, although you could simulate it with a local lazy val:

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

Regarding mutability - there is nothing holding you back from writing immutable data structures and avoid mutation. You can do this in Java or C as well. In fact, some immutable data structures rely on the lazy primitive to achieve better complexity bounds, but the lazy primitive can be simulated in other languages as well - at the cost of extra syntax and boilerplate.

You can always write immutable data structures, lazy computations and fully pure programs in Scala. The problem is that the Scala programming model allows writing non pure programs as well, so the type checker can't always infer some properties of the program (such as purity) which it could infer given that the programming model was more restrictive.

For example, in a language with pure expressions the a * a in the call-by-name definition above (a: =>Int) could be optimized to evaluate a only once, regardless of the call-by-name semantics. If the language allows side-effects, then such an optimization is not always applicable.

心是晴朗的。 2024-12-13 15:18:33

Scala 可以像您喜欢的那样纯粹和懒惰,但是 a) 编译器不会让您诚实地对待纯粹性,b) 需要一些额外的工作才能使其变得懒惰。这并没有什么太深奥的地方;如果您确实愿意,您甚至可以编写惰性的纯 Java 代码(如果您愿意,请参阅此处敢于;在 Java 中实现惰性需要大量的嵌套匿名内部类)。

纯度

Haskell 通过类型系统跟踪杂质,而 Scala 选择不走这条路,当你没有从一开始就将其作为目标时(并且当与完全不纯净的互操作性时),很难解决这类问题。像 Java 这样的语言是该语言的一个主要目标)。

也就是说,有些人相信< /a> 努力记录 Scala 类型系统中的效果是可能且值得的。但我认为 Scala 中的纯度最好被视为自律问题,并且您必须永远对第三方代码所谓的纯度持怀疑态度。

惰性

Haskell 默认情况下是惰性的,但可以通过在代码中添加一些注释来使其变得更严格...Scala 则相反:默认情况下严格,但使用 lazy 关键字和按名称参数可以使其变得更严格你想怎么懒就怎么懒。

Scala can be as pure and lazy as you like, but a) the compiler won't keep you honest with regards to purity and b) it will take a little extra work to make it lazy. There's nothing too profound about this; you can even write lazy and pure Java code if you really want to (see here if you dare; achieving laziness in Java requires eye-bleeding amounts of nested anonymous inner classes).

Purity

Whereas Haskell tracks impurities via the type system, Scala has chosen not to go that route, and it's difficult to tack that sort of thing on when you haven't made it a goal from the beginning (and also when interoperability with a thoroughly impure language like Java is a major goal of the language).

That said, some believe it's possible and worthwhile to make the effort to document effects in Scala's type system. But I think purity in Scala is best treated as a matter of self-discipline, and you must be perpetually skeptical about the supposed purity of third-party code.

Laziness

Haskell is lazy by default but can be made stricter with some annotations sprinkled in your code... Scala is the opposite: strict by default but with the lazy keyword and by-name parameters you can make it as lazy as you like.

清秋悲枫 2024-12-13 15:18:33

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

至于非严格性,事情是这样的……首先,如果你选择完全非严格性,你将放弃 Scala 的所有类。甚至 Scalaz 在大多数情况下也不是不严格的。如果你愿意自己构建一切,你就可以让你的方法变得不严格,让你的价值观变得懒惰。

接下来,我想知道隐式参数是否可以是非严格的,或者使它们成为非严格的会产生什么后果。我不认为有什么问题,但我可能是错的。

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

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

Feel free to keep things immutable. On the other hand, there's no side effect tracking, so you can't enforce or verify it.

As for non-strictness, here's the deal... First, if you choose to go completely non-strict, you'll be forsaking all of Scala's classes. Even Scalaz is not non-strict for the most part. If you are willing to build everything yourself, you can make your methods non-strict and your values lazy.

Next, I wonder if implicit parameters can be non-strict or not, or what would be the consequences of making them non-strict. I don't see a problem, but I could be wrong.

But, most problematic of all, function parameters are strict, and so are closures parameters.

So, while it is theoretically possible to go fully non-strict, it will be incredibly inconvenient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文