- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我了解 Ruby 和 Python 的产量。 Scala的yield有什么作用?
最佳答案
我认为公认的答案很好,但似乎很多人都未能捕获一些基本点。
首先,Scala 的 for 推导式相当于 Haskell 的 do 表示法,它只不过是多个一元运算组合的语法糖。由于此声明很可能不会帮助任何需要帮助的人,让我们再试一次......:-)
Scala 的 for
推导式是用于使用 map、flatMap
和 filter
组合多个操作的语法糖。或者foreach
。 Scala 实际上将 for
表达式转换为对这些方法的调用,因此提供它们的任何类或其子集都可以与 for 推导式一起使用。
首先,我们来谈谈翻译。有非常简单的规则:
这个
for(x <- c1; y <- c2; z <-c3) {...}
翻译成
c1.foreach(x => c2.foreach(y => c3.foreach(z => {...})))
这个
for(x <- c1; y <- c2; z <- c3) yield {...}
翻译成
c1.flatMap(x => c2.flatMap(y => c3.map(z => {...})))
这个
for(x <- c; if cond) yield {...}
在 Scala 2.7 上被翻译成
c.filter(x => cond).map(x => {...})
或者,在 Scala 2.8 上,进入
c.withFilter(x => cond).map(x => {...})
如果 withFilter
方法不可用,但 filter
可用,则回退到前者。有关详细信息,请参阅以下部分。
这个
for(x <- c; y = ...) yield {...}
翻译成
c.map(x => (x, ...)).map((x,y) => {...})
当您查看非常简单的 for
推导式时,map
/foreach
替代方案看起来确实更好。然而,一旦开始编写它们,您很容易迷失在括号和嵌套级别中。当这种情况发生时,for
理解通常会更加清晰。
我将展示一个简单的示例,并故意省略任何解释。您可以决定哪种语法更容易理解。
l.flatMap(sl => sl.filter(el => el > 0).map(el => el.toString.length))
或
for {
sl <- l
el <- sl
if el > 0
} yield el.toString.length
<小时/>
withFilter
Scala 2.8 引入了一种名为 withFilter
的方法,其主要区别在于,它不是返回新的经过过滤的集合,而是按需进行过滤。 filter
方法的行为是根据集合的严格性定义的。为了更好地理解这一点,让我们看一下带有 List
(严格)和 Stream
(非严格)的 Scala 2.7:
scala> var found = false
found: Boolean = false
scala> List.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
7
9
scala> found = false
found: Boolean = false
scala> Stream.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
之所以会出现这种差异,是因为 filter
立即与 List
一起应用,返回赔率列表 - 因为 found
为 false
。只有这样 foreach
才会被执行,但是,此时,更改 found
已经没有意义了,因为 filter
已经执行了。
对于Stream
,条件不会立即应用。相反,当 foreach
请求每个元素时,filter
会测试条件,这使得 foreach
能够通过 found
影响它>。为了清楚起见,下面是等效的 for 理解代码:
for (x <- List.range(1, 10); if x % 2 == 1 && !found)
if (x == 5) found = true else println(x)
for (x <- Stream.range(1, 10); if x % 2 == 1 && !found)
if (x == 5) found = true else println(x)
这导致了许多问题,因为人们期望 if
被视为按需,而不是预先应用于整个集合。
Scala 2.8 引入了 withFilter
,它始终是非严格的,无论集合的严格性如何。以下示例显示了 Scala 2.8 上使用两种方法的 List
:
scala> var found = false
found: Boolean = false
scala> List.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
7
9
scala> found = false
found: Boolean = false
scala> List.range(1,10).withFilter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
这会产生大多数人期望的结果,而不会改变过滤器
的行为方式。附带说明一下,在 Scala 2.7 和 Scala 2.8 之间,Range
从非严格更改为严格。
关于scala - Scala 的产量是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1052476/
使用 Python 3.4,我在此处得到 SyntaxError: invalid syntax: >>> xlist = [1,2,3,4,5] >>> [yield(x) for x in xli
在这篇文章 ( http://blogs.msdn.com/oldnewthing/archive/2008/08/13/8854601.aspx ) 中,有一个关于迭代器的流行问题和一个关于极端情况
在 Ruby 中,yield 关键字用于让出执行 block 的闭包。 这个关键字在 Python 语言中有何不同? 最佳答案 在 ruby 中,yield 是用于调用匿名函数的快捷方式。 Rub
这个问题在这里已经有了答案: check if function is a generator (13 个答案) 关闭 7 年前。 检查函数是否为生成器的可靠方法是什么,例如: let fn = f
jquery 中是否可以产生变量?我想在部分 View 中设置一个变量,根据该变量我将某个菜单项设置为事件状态。 我有一个菜单,我想在其中产生像这样的事件项目(在我的主布局 View 中): func
问题 是否可以将 yielding pytest fixtures(用于设置和拆卸)作为参数传递给测试函数? 上下文 我正在测试一个对象,该对象从单个目录中的文件读取数据/向文件写入数据。该目录的路径
我刚刚开始使用 Ruby,我在 Bloc 的类(class)中已经走了很长一段路,但现在我被困在与 yield 和 blocks 有关的练习上(我发现这是迄今为止最难掌握的概念说到学习 ruby
我一直在寻找这一点,但我还没有得到任何关于它的信息!。 我看了很多关于“ yield 返回”的视频和红色文章,我想我对它有更好的理解,但有一点我无法理解 我应该使用 yield return 的正确接
UPDATE(反映最先进的知识水平)状态:2017-05-12 进行此更新的原因是,当我问这个问题时,我并不知道我发现了有关Python3如何“在幕后”工作的信息。 从所有得出的结论是: 如果您为迭代
我正在尝试在 Atmel Studio 7 中为 Arduino 编写代码。为了使其与 Arduino IDE 相似,我正在尝试调整其库。 但是我已经被 delay() 阻止了,它使用了 yield(
我正在构建一个简单的 C++ 服务器,我在其中通过 POST 请求接收图像,将其发送到 GPU 进行处理,一旦我从 GPU 获得结果,就发回响应。 为了能够处理许多同时连接(并学习新的东西),我正在使
我想生成从每片叶子到树根的所有路径。我想用生成器来做,以节省内存(树可以很大)。这是我的代码: def paths(self, acc=[]): if self.is_leaf():
假设我有以下代码(缩小上下文以限制问题范围) public static IEnumerable GetThemColors(){ var ids = GetThePrimaryIds();
我想我也有同样的问题。 Using multiple yields to insert content 我尝试了这个解决方案。我试过 在我的 application.html.erb 中有 conte
我熟悉 yield 以返回值,这主要归功于 this question 但是当它在赋值的右边时,yield 会做什么呢? @coroutine def protocol(target=None):
function * d1 (p) { p-=1; yield p; p-=2; yield p; } var g=d1 (9); var h; console.l
以下代码在 golang 中实现了 yield 模式。作为一项实验,我正在实现一个all permutations 生成器。但是,当我将 slice A 返回到 channel 时,如果我不创建数组的
Node.js 现在有生成器。 我的理解是,生成器可用于编写看起来更加线性的代码,并避免回调 hell 和末日风格编码的金字塔。 所以到目前为止,我的理解是,在生成器内部,代码会一直执行,直到它到达“
我遇到的问题真的很奇怪。由于某种原因,我的 catch block 中的 put 没有在下面执行。这是我的传奇: function* postLoginFormSaga(action) { l
假设我只想快速使以下方法异步运行: ResultType SynchronousCode(ParamType x) { return SomeLongRunningWebRequest(x)
我是一名优秀的程序员,十分优秀!