Scala 的产量是多少?
我了解 Ruby 和 Python 的产量。 Scala的yield有什么作用?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我了解 Ruby 和 Python 的产量。 Scala的yield有什么作用?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(11)
我认为公认的答案很好,但似乎很多人都未能抓住一些基本点。
首先,Scala 的 for 推导式相当于 Haskell 的 do 表示法,它只不过是多个一元运算组合的语法糖。 由于这个语句很可能不会帮助任何需要帮助的人,所以让我们再试一次......:-)
Scala 的
for
推导式是使用 map、flatMap
和 组合多个操作的语法糖。过滤器。 或者foreach
。 Scala 实际上将for
表达式转换为对这些方法的调用,因此提供它们的任何类或其子集都可以与 for 推导式一起使用。首先,我们来谈谈翻译。 有非常简单的规则:
这个
翻译成
This
翻译成
This
在 Scala 2.7 上被翻译成
或者,在 Scala 2.8 上,进入
如果
withFilter
方法不可用,但filter
可用,则回退到前者。 有关详细信息,请参阅下面的部分。这个
翻译成
当你查看非常简单的
for
推导式时,map
/foreach
替代方案看起来确实如此, 更好的。 然而,一旦开始编写它们,您很容易迷失在括号和嵌套级别中。 当这种情况发生时,for
理解通常会更加清晰。我将展示一个简单的例子,并故意省略任何解释。 您可以决定哪种语法更容易理解。
或者
withFilter
Scala 2.8 引入了一种名为
withFilter
的方法,其主要区别在于,它不是返回一个新的、经过过滤的集合,而是按需进行过滤。filter
方法的行为是根据集合的严格性定义的。 为了更好地理解这一点,让我们看一下带有List
(严格)和Stream
(非严格)的 Scala 2.7:之所以会出现差异,是因为
filter 立即与
List
一起应用,返回赔率列表 - 因为found
为false
。 只有这样foreach
才会执行,但是此时,更改found
已经没有意义了,因为filter
已经执行了。对于
Stream
,条件不会立即应用。 相反,当foreach
请求每个元素时,filter
会测试条件,这使得foreach
能够通过found
影响它>。 澄清一下,这里是等效的 for 理解代码:这导致了很多问题,因为人们期望
if
被视为按需,而不是预先应用于整个集合。Scala 2.8 引入了
withFilter
,它始终是非严格的,无论集合的严格性如何。 以下示例显示了 Scala 2.8 上使用两种方法的List
:这会产生大多数人期望的结果,而无需更改
filter
的行为方式。 附带说明一下,在 Scala 2.7 和 Scala 2.8 之间,Range
从非严格更改为严格。I think the accepted answer is great, but it seems many people have failed to grasp some fundamental points.
First, Scala's
for
comprehensions are equivalent to Haskell'sdo
notation, and it is nothing more than a syntactic sugar for composition of multiple monadic operations. As this statement will most likely not help anyone who needs help, let's try again… :-)Scala's
for
comprehensions is syntactic sugar for composition of multiple operations with map,flatMap
andfilter
. Orforeach
. Scala actually translates afor
-expression into calls to those methods, so any class providing them, or a subset of them, can be used with for comprehensions.First, let's talk about the translations. There are very simple rules:
This
is translated into
This
is translated into
This
is translated on Scala 2.7 into
or, on Scala 2.8, into
with a fallback into the former if method
withFilter
is not available butfilter
is. Please see the section below for more information on this.This
is translated into
When you look at very simple
for
comprehensions, themap
/foreach
alternatives look, indeed, better. Once you start composing them, though, you can easily get lost in parenthesis and nesting levels. When that happens,for
comprehensions are usually much clearer.I'll show one simple example, and intentionally omit any explanation. You can decide which syntax was easier to understand.
or
withFilter
Scala 2.8 introduced a method called
withFilter
, whose main difference is that, instead of returning a new, filtered, collection, it filters on-demand. Thefilter
method has its behavior defined based on the strictness of the collection. To understand this better, let's take a look at some Scala 2.7 withList
(strict) andStream
(non-strict):The difference happens because
filter
is immediately applied withList
, returning a list of odds -- sincefound
isfalse
. Only thenforeach
is executed, but, by this time, changingfound
is meaningless, asfilter
has already executed.In the case of
Stream
, the condition is not immediatelly applied. Instead, as each element is requested byforeach
,filter
tests the condition, which enablesforeach
to influence it throughfound
. Just to make it clear, here is the equivalent for-comprehension code:This caused many problems, because people expected the
if
to be considered on-demand, instead of being applied to the whole collection beforehand.Scala 2.8 introduced
withFilter
, which is always non-strict, no matter the strictness of the collection. The following example showsList
with both methods on Scala 2.8:This produces the result most people expect, without changing how
filter
behaves. As a side note,Range
was changed from non-strict to strict between Scala 2.7 and Scala 2.8.它用于 序列推导式(如 Python 的列表推导式和生成器,您可以在其中使用
产量
)。它与
for
结合应用,并将新元素写入结果序列中。简单示例(来自 scala-lang)
F# 中相应的表达式将是
Linq 中的or
。
Ruby 的
yield
有不同的效果。It is used in sequence comprehensions (like Python's list-comprehensions and generators, where you may use
yield
too).It is applied in combination with
for
and writes a new element into the resulting sequence.Simple example (from scala-lang)
The corresponding expression in F# would be
or
in Linq.
Ruby's
yield
has a different effect.是的,正如 Earwicker 所说,它几乎相当于 LINQ 的
select
,并且与 Ruby 和 Python 的yield
关系不大。 基本上,在 C# 中,您可以用 Scala
编写。同样重要的是要了解
for
推导式不仅适用于序列,还适用于定义某些方法的任何类型,就像 LINQ 一样:map
,则它允许包含for
表达式单发电机。
flatMap
以及map
,则它允许for
表达式组成几个发电机。
foreach
,则它允许不带yield的for
循环(无论是单个生成器还是多个生成器)。filter
,则允许以if
开头的for
过滤表达式在
for
表达式中。Yes, as Earwicker said, it's pretty much the equivalent to LINQ's
select
and has very little to do with Ruby's and Python'syield
. Basically, where in C# you would writein Scala you have instead
It's also important to understand that
for
-comprehensions don't just work with sequences, but with any type which defines certain methods, just like LINQ:map
, it allowsfor
-expressions consisting of asingle generator.
flatMap
as well asmap
, it allowsfor
-expressions consistingof several generators.
foreach
, it allowsfor
-loops without yield (both with single and multiple generators).filter
, it allowsfor
-filter expressions starting with anif
in the
for
expression.除非您从 Scala 用户那里得到更好的答案(我不是),否则这是我的理解。
它仅作为以
for
开头的表达式的一部分出现,该表达式说明如何从现有列表生成新列表。就像这样:
所以每个输入都有一个输出项(尽管我相信有一种删除重复项的方法)。
这与其他语言中由yield启用的“命令式延续”有很大不同,它提供了一种从具有几乎任何结构的命令式代码生成任何长度的列表的方法。
(如果您熟悉 C#,它更接近 LINQ 的
select
运算符而不是yield return
)。Unless you get a better answer from a Scala user (which I'm not), here's my understanding.
It only appears as part of an expression beginning with
for
, which states how to generate a new list from an existing list.Something like:
So there's one output item for each input (although I believe there's a way of dropping duplicates).
This is quite different from the "imperative continuations" enabled by yield in other languages, where it provides a way to generate a list of any length, from some imperative code with almost any structure.
(If you're familiar with C#, it's closer to LINQ's
select
operator than it is toyield return
).考虑以下内容进行理解
如下所示大声朗读可能会有所帮助
” 对于每个整数
i
,如果它大于3
,则产量 (产生)i
并将其添加到列表A
。”在数学方面set-builder 表示法,上面的 for 理解类似于
可以读作
"For每个整数 ,如果它大于,那么它是集合 ." 的成员
或
"< img src="https://latex.codecogs.com/gif.latex?A" alt="A"> 是所有整数的集合 ,使得每个 大于 。"
Consider the following for-comprehension
It may be helpful to read it out loud as follows
"For each integer
i
, if it is greater than3
, then yield (produce)i
and add it to the listA
."In terms of mathematical set-builder notation, the above for-comprehension is analogous to
which may be read as
"For each integer , if it is greater than , then it is a member of the set ."
or alternatively as
" is the set of all integers , such that each is greater than ."
Scala 中的关键字
yield
只是语法糖,可以轻松地用map
替换,如 Daniel Sobral 已经详细解释了。另一方面,如果您正在寻找类似于
yield
绝对具有误导性。 moin/Generators" rel="noreferrer">Python 中的。 请参阅此SO线程以获取更多信息: 什么是首选方法在 Scala 中实现“yield”?The keyword
yield
in Scala is simply syntactic sugar which can be easily replaced by amap
, as Daniel Sobral already explained in detail.On the other hand,
yield
is absolutely misleading if you are looking for generators (or continuations) similar to those in Python. See this SO thread for more information: What is the preferred way to implement 'yield' in Scala?Yield 类似于 for 循环,它有一个我们看不到的缓冲区,并且对于每个增量,它都会不断地将下一个项目添加到缓冲区中。 当 for 循环运行结束时,它将返回所有生成值的集合。 Yield 可以用作简单的算术运算符,甚至可以与数组结合使用。
这里有两个简单的例子,可以帮助您更好地理解
res: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 6, 9, 12, 15)
res: Seq[(Int, Char)] = List((1, a)、(1,b)、(1,c)、(2,a)、(2,b)、(2,c)、(3,a)、(3,b)、(3,c) )
希望这可以帮助!!
Yield is similar to for loop which has a buffer that we cannot see and for each increment, it keeps adding next item to the buffer. When the for loop finishes running, it would return the collection of all the yielded values. Yield can be used as simple arithmetic operators or even in combination with arrays.
Here are two simple examples for your better understanding
res: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 6, 9, 12, 15)
res: Seq[(Int, Char)] = List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c))
Hope this helps!!
这两段代码是等价的。
这两段代码也是等价的。
Map 与产量一样灵活,反之亦然。
These two pieces of code are equivalent.
These two pieces of code are also equivalent.
Map is as flexible as yield and vice-versa.
请注意,这两个 for 表达式都使用 yield 关键字:
在 for 之后使用 yield 是“秘密武器”,它表示“我想要使用所示的算法,从我在 for 表达式中迭代的现有集合中生成一个新集合。”
取自此处
Notice that both of those for-expressions use the yield keyword:
Using yield after for is the “secret sauce” that says, “I want to yield a new collection from the existing collection that I’m iterating over in the for-expression, using the algorithm shown.”
taken from here
根据Scala 文档,它明确表示“从现有集合中产生一个新集合”。
另一个 Scala 文档说:“Scala 提供了一种轻量级符号来表达序列推导式。推导式的形式为
for
(枚举)yield e
,其中 enums 指的是以分号分隔的枚举器列表。枚举器要么是引入新变量的生成器,要么是过滤器。According to the Scala documentation, it clearly says "yield a new collection from the existing collection".
Another Scala documentation says, "Scala offers a lightweight notation for expressing sequence comprehensions. Comprehensions have the form
for
(enums)yield e
, where enums refers to a semicolon-separated list of enumerators. An enumerator is either a generator which introduces new variables, or it is a filter. "yield 比 map() 更灵活,请参见下面的示例,
yield 将打印结果,如:List(5, 6),这很好,
而 map() 将返回结果,如:List(false, false, true, true, true),这可能不是你想要的。
yield is more flexible than map(), see example below
yield will print result like: List(5, 6), which is good
while map() will return result like: List(false, false, true, true, true), which probably is not what you intend.