gpt4 book ai didi

scala - 如何表达[42 | x == y] 与理解?

转载 作者:行者123 更新时间:2023-12-01 10:00:50 25 4
gpt4 key购买 nike

我有一些代码片段,我在其中生成多个列表(通过 for comprehensions),然后将它们连接起来。有一些单元素列表,但这是行不通的。在 Haskell 中,我会做类似的事情

[42 | i == j]

相当于

(do guard (i == j)
return 42) :: [Int]

(guard (i == j) >>= \_ -> return 1) :: [Int]

在 Scala 中我尝试过

for (if i == j) yield 42

但它说“简单模式的非法开始”。

In an answer to what Scala's yield is作者说“Scala 的“for comprehensions”等同于 Haskell 的“do”符号”。

此外,在 Scala website 上它说“理解具有 for (enums) yield e 的形式,其中 enums 是指以分号分隔的枚举器列表。枚举器要么是引入新变量的生成器,要么是过滤器” .但很明显,情况并非如此,因为过滤器似乎只允许 生成器之后。

目前我在用

if (i == j) List(42) else Nil

对于这种特殊情况,我可能不喜欢 for comprehension 语法,而是使用 if-then-else 代替。在 Haskell 中,由于与数学集合构建器符号的相似性,它看起来相当不错。

我的问题不是关于样式,而是更多关于技术细节:为什么 Haskell 和 Scala 在这个特定情况下存在差异?为什么 for (if i == j) yield 42 不工作?

最佳答案

最接近的等价物 [42 | i == j]可能是 for (x <- List(42) if i == j) yield x .

for (if i == j) yield 42是非法的,因为过滤器(if 部分)必须跟在某个生成器之后(在我的示例中为 x <- List(42))。

Scala language specification状态(6.19 For Comprehensions and For Loops):

语法:

Expr1       ::= ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’)
{nl} [‘yield’] Expr
Enumerators ::= Generator {semi Enumerator}
Enumerator ::= Generator
| Guard
| ‘val’ Pattern1 ‘=’ Expr
Generator ::= Pattern1 ‘<-’ Expr [Guard]
Guard ::= ‘if’ PostfixExpr

如您所见,Enumerators 中至少需要一个生成器.

编辑:

顺便说一句,我认为if (i == j) List(42) else Nil是正确的做法,因为它不是 Haskell。它很干净而且很可能更快,因为它只构造一次列表并且不调用任何其他方法。

我的例子被编译器翻译成List(42) withFilter (x => i == j) map (x => x) (它实际上可能被优化,我不确定)并且可以缩写为 List(42) filter (x => i == j) .你可以看到,它构造了初始列表,然后调用了一个创建新列表的方法,这个方法采用匿名函数,在 Scala 中它也是一个对象(但可能它也被优化了)。我认为做这么简单的工作效率很低。

关于scala - 如何表达[42 | x == y] 与理解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16500819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com