| Thread overview | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
July 29, 2012 yield iteration | ||||
|---|---|---|---|---|
| ||||
A subthread of the "Impressed" thread revolved around D's lack of a yield mechanism for iteration.
Nick Sabalausky mentioned his earlier attempt to create a library based yield which unfortunately was too slow to compete with explicit opApply/ranges [1].
I took a shot at it. It's fast. The resulting code is reasonably pretty. But it doesn't provide a range interface, just opApply.
---
module yielder;
import core.thread;
/**
Examples:
---
import yielder;
import std.stdio;
auto y = new class Yielder!int {
final void yielding() {
yield(0);
yield(13);
yield(42);
}
};
foreach(x; y) {
writeln(x);
}
---
*/
class Yielder(E) {
abstract void yielding();
this() {
this.fiber = new Fiber(&yielding);
}
private {
Fiber fiber;
int result;
int delegate(ref E) callback;
}
final int opApply(int delegate(ref E) cb) {
callback = cb;
result = 0;
fiber.reset();
fiber.call();
return result;
}
final void yield(ref E value) {
result = callback(value);
if(result != 0) {
Fiber.yield();
}
}
final void yield(E value) {
yield(value);
}
}
---
[1] https://semitwist.com/articles/article/view/combine-coroutines-and-input-ranges-for-dead-simple-d-iteration
| ||||
July 29, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to anonymous | anonymous: > A subthread of the "Impressed" thread revolved around D's lack of a yield mechanism for iteration. The yield as in Python is so useful and handy, and I miss it often in D. This is an example of Inverse Gray iterator (Sloane series A006068) Python2 code from: http://code.activestate.com/recipes/221457/ def A006068(): yield 0 for x in A006068(): if x & 1: yield 2 * x + 1 yield 2 * x else: if x: yield 2 * x yield 2 * x + 1 Turning that in D code that uses opApply is not hard, but the code inflates 3X, and you can't use most std.algorithm on it. I have discussed the situation a little here: http://d.puremagic.com/issues/show_bug.cgi?id=5660 Bye, bearophile | |||
July 29, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile |
>
> This is an example of Inverse Gray iterator (Sloane series A006068) Python2 code from:
> http://code.activestate.com/recipes/221457/
>
> def A006068():
> yield 0
> for x in A006068():
> if x & 1:
> yield 2 * x + 1
> yield 2 * x
> else:
> if x:
> yield 2 * x
> yield 2 * x + 1
>
Does this spawn linear many generators?
| |||
July 29, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to anonymous | Ideally it would look like this:
struct Map(alias fun, R){
R range;
mixin YieldInputRange!q{
for(; !range.empty; range.popFront())
yield fun(range.front);
}
static if(is(typeof(range.save))) @property auto save(){
return Map!(fun, R)(range.save);
}
...
}
Or as a built-in:
struct Map(alias fun, R){
R range;
yield {
for(; !range.empty; range.popFront())
yield fun(x);
}
static if(is(typeof(range.save))) @property auto save(){
return Map!(fun, R)(range.save);
}
...
}
| |||
July 29, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 07/29/2012 04:48 PM, Timon Gehr wrote: > Ideally it would look like this: > > struct Map(alias fun, R){ > R range; > mixin YieldInputRange!q{ > for(; !range.empty; range.popFront()) > yield fun(range.front); > } > static if(is(typeof(range.save))) @property auto save(){ > return Map!(fun, R)(range.save); > } > ... > } > > Or as a built-in: > > struct Map(alias fun, R){ > R range; > yield { > for(; !range.empty; range.popFront()) > yield fun(x); yield fun(range.front); // oops > } > static if(is(typeof(range.save))) @property auto save(){ > return Map!(fun, R)(range.save); > } > ... > } | |||
July 29, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | Tobias Pankrath:
> Does this spawn linear many generators?
I have written this little test code, Python2.6+:
count = 0
def A006068():
global count
count += 1
yield 0
for x in A006068():
if x & 1:
yield 2 * x + 1
yield 2 * x
else:
if x:
yield 2 * x
yield 2 * x + 1
from itertools import islice
def main():
global count
for p in xrange(15):
n = 2 ** p
count = 0
print sum(1 for _ in islice(A006068(), 0, n)), count
main()
The output seems to show that it spawns only logarithmically:
1 1
2 2
4 3
8 4
16 5
32 6
64 7
128 8
256 9
512 10
1024 11
2048 12
4096 13
8192 14
16384 15
Bye,
bearophile
| |||
July 31, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | "bearophile" , dans le message (digitalmars.D:173647), a écrit : > Turning that in D code that uses opApply is not hard, but the code inflates 3X, and you can't use most std.algorithm on it. I believe most std.algorithm that work on input range could be made to work with opApply, or opApply-like delegates. It just wouldn't be particularly efficient unless agressive inlining is used. For example, filter could work like this for opApply-like delegates: template filter(pred) { auto filter(T)(int delegate(int delegate(ref T)) apply) { return (int delegate(ref T) dg) { return apply( (ref T t) { return pred(t)? dg(t): 1; }); } } } -- Christophe | |||
July 31, 2012 Re: yield iteration | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christophe Travert | Christophe Travert, dans le message (digitalmars.D:173787), a écrit : > "bearophile" , dans le message (digitalmars.D:173647), a écrit : >> Turning that in D code that uses opApply is not hard, but the code inflates 3X, and you can't use most std.algorithm on it. > > I believe most std.algorithm that work on input range could be made to work with opApply, or opApply-like delegates. It just wouldn't be particularly efficient unless agressive inlining is used. > > For example, filter could work like this for opApply-like delegates: > > template filter(pred) > { > auto filter(T)(int delegate(int delegate(ref T)) apply) > { > return (int delegate(ref T) dg) > { > return apply( (ref T t) { return pred(t)? dg(t): 1; }); ^should read 0 > } > } > } > > -- > Christophe | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply