我最近偶然发现了这段代码:
function xrange($min, $max)
{
for ($i = $min; $i <= $max; $i++) {
yield $i;
}
}
Run Code Online (Sandbox Code Playgroud)
我以前从未见过这个yield关键字.试着运行我得到的代码
解析错误:语法错误,第x行意外的T_VARIABLE
那么这个yield关键字是什么?它甚至是有效的PHP吗?如果是,我该如何使用它?
我yield()对Java 中方法的使用有点困惑,特别是在下面的示例代码中.我还读过yield()'用于防止执行线程'.
我的问题是:
我相信下面的代码在使用yield()和不使用时都会产生相同的输出.它是否正确?
事实上,什么是主要用途yield()?
在哪些方面与方法yield()不同?join()interrupt()
代码示例:
public class MyRunnable implements Runnable {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
for(int i=0; i<5; i++) {
System.out.println("Inside main");
}
}
public void run() {
for(int i=0; i<5; i++) {
System.out.println("Inside run");
Thread.yield();
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用和不使用上面的代码我获得相同的输出yield():
Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside …Run Code Online (Sandbox Code Playgroud) 以下是可以的:
try
{
Console.WriteLine("Before");
yield return 1;
Console.WriteLine("After");
}
finally
{
Console.WriteLine("Done");
}
Run Code Online (Sandbox Code Playgroud)
该finally块在整个执行完毕后运行(IEnumerator<T>支持IDisposable提供一种方法来确保即使枚举在完成之前被放弃).
但这不是好事:
try
{
Console.WriteLine("Before");
yield return 1; // error CS1626: Cannot yield a value in the body of a try block with a catch clause
Console.WriteLine("After");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Run Code Online (Sandbox Code Playgroud)
假设(为了参数)WriteLinetry块中的一个或另一个调用抛出异常.在catch块中继续执行有什么问题?
当然,收益率回报部分(目前)无法抛出任何东西,但是为什么要阻止我们封闭try/ catch处理在之前或之后抛出的异常yield return?
更新:Eric Lippert在这里有一个有趣的评论 - 似乎他们已经有足够的问题正确实现try/finally行为!
编辑:此错误的MSDN页面是:http://msdn.microsoft.com/en-us/library/cs1x15az.aspx.但这并没有解释为什么.
我遇到了以下Ruby代码:
class MyClass
attr_accessor :items
...
def each
@items.each{|item| yield item}
end
...
end
Run Code Online (Sandbox Code Playgroud)
该each方法有什么作用?特别是,我不明白是什么yield.
我在JavaScript中读到了yield关键字,我需要在我的项目中使用它.我读到这个关键字是从某个版本的JS开始实现的,所以我认为旧浏览器不支持它(对吧?).
有没有办法检查yield关键字是否受支持?或者至少有办法检查JS的版本是否大于或等于实现该关键字的版本(1.7)?
是否可以在不评估每个值的情况下将yield用作迭代器?
这很容易实现复杂的列表生成,然后你需要将其转换成一个常见的任务Iterator,因为你不需要一些结果......
请考虑以下代码.
std::vector<result_data> do_processing()
{
pqxx::result input_data = get_data_from_database();
return process_data(input_data);
}
std::vector<result_data> process_data(pqxx::result const & input_data)
{
std::vector<result_data> ret;
pqxx::result::const_iterator row;
for (row = input_data.begin(); row != inpupt_data.end(); ++row)
{
// somehow populate output vector
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
当我在考虑是否可以期待返回值优化(RVO)时,我发现Jerry Coffin的这个答案 [强调我的]:
至少IMO,这通常是一个糟糕的主意,但不是出于效率原因.这是一个糟糕的主意,因为有问题的函数通常应该写成通过迭代器生成输出的通用算法.几乎任何接受或返回容器而不是在迭代器上运行的代码都应该被认为是可疑的.
不要误解我的意思:有时候传递类似于集合的对象(例如字符串)是有意义的,但对于引用的例子,我会考虑传递或返回向量一个糟糕的想法.
有一些Python背景,我非常喜欢Generators.实际上,如果它是Python,我会把上面的函数写成一个Generator,即避免在其他任何事情发生之前处理整个数据的必要性.例如这样:
def process_data(input_data):
for item in input_data:
# somehow process items
yield result_data
Run Code Online (Sandbox Code Playgroud)
如果我正确地解释了Jerry Coffins的说法,这就是他的建议,不是吗?如果是这样,我如何在C++中实现它?
在Scala语言中,我想编写一个在给定范围内产生奇数的函数.迭代偶数时,该函数会打印一些日志.该函数的第一个版本是:
def getOdds(N: Int): Traversable[Int] = {
val list = new mutable.MutableList[Int]
for (n <- 0 until N) {
if (n % 2 == 1) {
list += n
} else {
println("skip even number " + n)
}
}
return list
}
Run Code Online (Sandbox Code Playgroud)
如果省略打印日志,则实现变得非常简单:
def getOddsWithoutPrint(N: Int) =
for (n <- 0 until N if (n % 2 == 1)) yield n
Run Code Online (Sandbox Code Playgroud)
但是,我不想错过记录部分.如何更紧凑地重写第一个版本?如果它可以被重写类似于这将是伟大的:
def IWantToDoSomethingSimilar(N: Int) =
for (n <- 0 until N) if (n % 2 == 1) yield …Run Code Online (Sandbox Code Playgroud) 有没有人试图使用生成器来获得Underscore JS或lodash(或任何ES5标准函数)?
如果我们有一个数组var myArray = [1,2,3,4,6];
我们希望每次都有它.
在非发电机的情况下,你会很简单
myArray.forEach(function(k) {
console.log(k);
});
Run Code Online (Sandbox Code Playgroud)
但是,当你无法在非生成器函数内部产生时,所以如果在这个循环中我们必须做一些异步工作,你需要做以下事情.
var foreach = function* (arr, fn) {
var i;
for (i = 0; i < arr.length; i++) {
yield * fn(arr[i], i);
}
};
yield* foreach(myArray, function* (k) {
var a = yield fs.readFile();
});
Run Code Online (Sandbox Code Playgroud)
哪种糟透了.
有人知道如何让匿名函数与生成器一起工作吗?因此,我们失去了整个lodash库.
注意:我正在使用Traceur将我的代码编译成ES6,并启用了生成器.
注意:我没有使用co().我正在使用下面看到的自定义生成器功能
var run = function(generatorFunction) {
var generatorItr = generatorFunction(resume);
function resume(callbackValue) {
generatorItr.next(callbackValue);
}
generatorItr.next();
};
Run Code Online (Sandbox Code Playgroud) 这是我的一段代码,定义了两个生成器:
one_line_gen = (x for x in range(3))
def three_line_gen():
yield 0
yield 1
yield 2
Run Code Online (Sandbox Code Playgroud)
当我执行:
for x in one_line_gen:
print x
for x in one_line_gen:
print x
Run Code Online (Sandbox Code Playgroud)
结果如预期:
0
1
2
Run Code Online (Sandbox Code Playgroud)
但是,如果我执行:
for x in three_line_gen():
print x
for x in three_line_gen():
print x
Run Code Online (Sandbox Code Playgroud)
结果是:
0
1
2
0
1
2
Run Code Online (Sandbox Code Playgroud)
为什么?我以为任何发电机只能使用一次.
yield-keyword ×10
generator ×4
javascript ×2
scala ×2
yield ×2
c# ×1
c++ ×1
continue ×1
coroutine ×1
ecmascript-6 ×1
exception ×1
function ×1
iterator ×1
java ×1
keyword ×1
php ×1
php-5.5 ×1
python ×1
ruby ×1
yield-return ×1