digitalmars.D - Re: Full closures for D
- Mikola Lysenko <mclysenk mtu.edu> Nov 05 2007
- "Craig Black" <cblack ara.com> Nov 05 2007
- BCS <BCS pathlink.com> Nov 05 2007
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> Nov 05 2007
- Daniel Keep <daniel.keep.lists gmail.com> Nov 05 2007
- BCS <BCS pathlink.com> Nov 05 2007
- Daniel Keep <daniel.keep.lists gmail.com> Nov 05 2007
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> Nov 06 2007
- Kevin Bealer <kevinbealer gmail.com> Nov 05 2007
- torhu <no spam.invalid> Nov 05 2007
I'm excited. For the first time it is now possible to do futures in 7 lines of code: T delegate() future(T)(lazy T expr) { T res; auto t = new Thread({res = expr();}); t.start; return { t.wait; return res; } } Which could then be used as follows: auto hard_result = future( hard_expression ); // Do stuff ... use_result(hard_result());
Nov 05 2007
"Mikola Lysenko" <mclysenk mtu.edu> wrote in message news:fgns3v$1b13$1 digitalmars.com...I'm excited. For the first time it is now possible to do futures in 7 lines of code: T delegate() future(T)(lazy T expr) { T res; auto t = new Thread({res = expr();}); t.start; return { t.wait; return res; } } Which could then be used as follows: auto hard_result = future( hard_expression ); // Do stuff ... use_result(hard_result());
Very cool stuff! Did you test this code to see if it actually works? A little off topic, but I was looking at your code and wondering if "lazy" always means that the expression becomes a delegate? When a template is used, the compiler could embed the expression directly rather than creating a delegate. Since D is big on compile-time optimization, I was wondering if it does this. -Craig
Nov 05 2007
Craig Black wrote:"Mikola Lysenko" <mclysenk mtu.edu> wrote in message news:fgns3v$1b13$1 digitalmars.com...I'm excited. For the first time it is now possible to do futures in 7 lines of code: T delegate() future(T)(lazy T expr) { T res; auto t = new Thread({res = expr();}); t.start; return { t.wait; return res; } } Which could then be used as follows: auto hard_result = future( hard_expression ); // Do stuff ... use_result(hard_result());
Very cool stuff! Did you test this code to see if it actually works? A little off topic, but I was looking at your code and wondering if "lazy" always means that the expression becomes a delegate? When a template is used, the compiler could embed the expression directly rather than creating a delegate. Since D is big on compile-time optimization, I was wondering if it does this. -Craig
string mixins are fun: typeof(mixin(expr)) delegate() future(char[] expr)() { typeof(mixin(expr)) res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; } } auto hard_result = future!("hard_expression"); // Do stuff ... use_result(hard_result()); NOTE: this runs into the issue that there is no way to get a template to play with the local variables of a function. If there were a way to do this I can think of a number of very cool things that could be done.
Nov 05 2007
BCS wrote:string mixins are fun: typeof(mixin(expr)) delegate() future(char[] expr)() { typeof(mixin(expr)) res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; } } auto hard_result = future!("hard_expression"); // Do stuff ... use_result(hard_result()); NOTE: this runs into the issue that there is no way to get a template to play with the local variables of a function. If there were a way to do this I can think of a number of very cool things that could be done.
Yea, bummer :| I would have expected this to work: char[] bar(char[] foo) { char[] tmp; tmp ~= "alias "; foreach(p; foo) if (p == ',') tmp ~= ", alias "; else tmp ~= p; return tmp; } template future(char[] aliases, char[] expr) { mixin(typeof(mixin(expr)).stringof ~ ` delegate() future(` ~ bar(aliases) ~ `)() { ` ~ typeof(mixin(expr)).stringof ~ ` res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; }; }`); } void main() { int a = 1, b = 2; auto hard_result = future!("a,b", "a+b+39")!()(); } Seems like Walter has at least two bugs to solve before that happens..
Nov 05 2007
Jari-Matti Mäkelä wrote:BCS wrote:string mixins are fun: typeof(mixin(expr)) delegate() future(char[] expr)() { typeof(mixin(expr)) res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; } } auto hard_result = future!("hard_expression"); // Do stuff ... use_result(hard_result()); NOTE: this runs into the issue that there is no way to get a template to play with the local variables of a function. If there were a way to do this I can think of a number of very cool things that could be done.
Yea, bummer :| I would have expected this to work: char[] bar(char[] foo) { char[] tmp; tmp ~= "alias "; foreach(p; foo) if (p == ',') tmp ~= ", alias "; else tmp ~= p; return tmp; } template future(char[] aliases, char[] expr) { mixin(typeof(mixin(expr)).stringof ~ ` delegate() future(` ~ bar(aliases) ~ `)() { ` ~ typeof(mixin(expr)).stringof ~ ` res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; }; }`); } void main() { int a = 1, b = 2; auto hard_result = future!("a,b", "a+b+39")!()(); } Seems like Walter has at least two bugs to solve before that happens..
It's not a bug that future can't see a or b. They're called "visibility rules" and we have them for a reason, boy. Without rules, there's just *chaos* and chaos is... ugh, I don't even want to *think* about it. You could cheat and do this, though: void main() { int a = 1, b = 2; auto hard_result = mixin(future("a,b","a+b+39")); } Since the string mixin gets expanded into the context of the function. But, as you can see, it's ugly and clumsy. Just stick to lazy arguments for Pete's sake :P -- Daniel
Nov 05 2007
Daniel Keep wrote:It's not a bug that future can't see a or b. They're called "visibility rules" and we have them for a reason, boy. Without rules, there's just *chaos* and chaos is... ugh, I don't even want to *think* about it.
It would be nice to have a way to say "reach around these rules right now"
Nov 05 2007
BCS wrote:Daniel Keep wrote:It's not a bug that future can't see a or b. They're called "visibility rules" and we have them for a reason, boy. Without rules, there's just *chaos* and chaos is... ugh, I don't even want to *think* about it.
It would be nice to have a way to say "reach around these rules right now"
I believe this is what AST macros will be for. :) -- Daniel
Nov 05 2007
Daniel Keep wrote:Jari-Matti Mäkelä wrote:BCS wrote:string mixins are fun: typeof(mixin(expr)) delegate() future(char[] expr)() { typeof(mixin(expr)) res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; } } auto hard_result = future!("hard_expression"); // Do stuff ... use_result(hard_result()); NOTE: this runs into the issue that there is no way to get a template to play with the local variables of a function. If there were a way to do this I can think of a number of very cool things that could be done.
Yea, bummer :| I would have expected this to work: char[] bar(char[] foo) { char[] tmp; tmp ~= "alias "; foreach(p; foo) if (p == ',') tmp ~= ", alias "; else tmp ~= p; return tmp; } template future(char[] aliases, char[] expr) { mixin(typeof(mixin(expr)).stringof ~ ` delegate() future(` ~ bar(aliases) ~ `)() { ` ~ typeof(mixin(expr)).stringof ~ ` res; auto t = new Thread({res = mixin(expr);}); t.start; return { t.wait; return res; }; }`); } void main() { int a = 1, b = 2; auto hard_result = future!("a,b", "a+b+39")!()(); } Seems like Walter has at least two bugs to solve before that happens..
It's not a bug that future can't see a or b. They're called "visibility rules" and we have them for a reason, boy. Without rules, there's just *chaos* and chaos is... ugh, I don't even want to *think* about it.
You probably didn't notice but I used alias parameters there. So it should be very much possible to refer to the variables after that. Made a small bug though, should have beenauto hard_result = future!("a,b", "a+b+39")!(a,b)();
or perhaps char[] Future(char[] a, char[] b) { return `future!("` ~ a ~ `","` ~ b ~ `")!(` ~ a ~ `)`; } auto hard_result = mixin(Future("a,b", "a+b+39"))();You could cheat and do this, though: void main() { int a = 1, b = 2; auto hard_result = mixin(future("a,b","a+b+39")); } Since the string mixin gets expanded into the context of the function.
Alias parameters work much better.
Nov 06 2007
My futurism library has support for the kind of thing you are describing. Two of the several syntaxes it supports are shown here; both of these are for reading two disk files in parallel. // Read the contents of two files in parallel: char[] read_file(char[] fname) { return cast(char[]) read(fname1); } auto f1 = make_future(& read_file, fname1); auto f2 = make_future(& read_file, fname2); // Get the results - will block until each read() is done. char[] fv1 = f1.value; char[] fv2 = f2.value; And this: alias Future!(char[]) FString; char[] fname1 = "a.txt", fname2 = "b.txt"; FString f1 = new FString({ return cast(char[]) read(fname1); }); FString f2 = new FString({ return cast(char[]) read(fname2); }); // Get the results - will block until each read() is done. char[] fv1 = f1.value; char[] fv2 = f2.value; You can find it at dsource.org/projects/futurism. It's a few more than 7 lines, but a lot of it is thread pool management and so on. It took a bit of trial and error and some newsgroup chat to nail down all the syntax for capturing arguments like the fname1 shown here. (Maybe some of that would not be needed now that full closures exist.) Kevin
Nov 05 2007
Mikola Lysenko wrote:I'm excited. For the first time it is now possible to do futures in 7 lines of code: T delegate() future(T)(lazy T expr) { T res; auto t = new Thread({res = expr();}); t.start; return { t.wait; return res; } } Which could then be used as follows: auto hard_result = future( hard_expression ); // Do stuff ... use_result(hard_result());
I tested your code and got this: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION(0xc0000005) at (0x00930f80) ->us #0 ?? () #1 0x00405191 in MFZi std.thread.Thread.run () from thread #2 0x0040fd99 in ___threadstartex 4 () from threadex -> Something's wrong, but I'm not sure what. res is correctly put on the heap, so it's not that.
Nov 05 2007