digitalmars.D - Internal and external iteration, fibers
- bearophile (18/18) Jan 15 2013 The author of the experimental language Magpie is very
- Sean Kelly (14/26) Jan 15 2013 past I have read a very nice blog post about the unusual bootstrapped =
- Nick Sabalausky (31/42) Jan 18 2013 D has problems in this area, there's at least three ways to do it and
- Timon Gehr (3/7) Jan 18 2013 My shot at it: http://dpaste.dzfl.pl/baa538af
- Artur Skawina (156/165) Jan 20 2013 What doesn't work?
- qznc (3/19) Jan 19 2013 Is this also known as protothreads?
- Nick Sabalausky (3/24) Jan 19 2013 Yea. In fact, that's the exact same lib I've used.
- Timon Gehr (4/28) Jan 19 2013 This can be implemented a lot better looking in D. (My quick hack
- Philippe Sigaud (3/4) Jan 20 2013 Almost there. I almost have macros, even. But the generated parser is
- deadalnix (2/37) Jan 20 2013 DSEL ?
- Philippe Sigaud (5/9) Jan 20 2013 Domain-Specific Embedded Language, I guess.
- Nick Sabalausky (5/37) Jan 20 2013 If we need to resort to using D-as-a-DSL-inside-D to get decent
- deadalnix (4/8) Jan 20 2013 A good part of the job is done with Fibers. The biggest problem I
- Nick Sabalausky (16/25) Jan 21 2013 That's no good for general-purpose, then. Fibers may be light-weight
- deadalnix (4/7) Jan 21 2013 Can you explain more what a stackless fiber is ? From the linked
- Timon Gehr (3/9) Jan 21 2013 A stackless fiber does not have the execution stack as part of its
- deadalnix (4/18) Jan 21 2013 Ho yeah, I looked at the implementation. It is mostly made of
- Nick Sabalausky (13/34) Jan 21 2013 I don't know whether or not it can be done in D. But, if it can be
- Jacob Carlborg (5/16) Jan 21 2013 I know people don't like it but I have to say, this seems it could be a
- Rob T (8/10) Jan 21 2013 It would be just as ugly as C macros. Well maybe not as ugly, but
- deadalnix (4/28) Jan 21 2013 I was thinking the same thing, but don't wanted to bug people.
- Daniel Murphy (2/10) Jan 21 2013
- Daniel Murphy (5/14) Jan 21 2013 AST macros are just compiler support pushed into user code/libraries.
- Jacob Carlborg (8/11) Jan 21 2013 Would that be so bad idea, to have a fixed AST representation? The AST
- Daniel Murphy (7/14) Jan 22 2013 It depends how much information is in the AST you give the user. Just
- Jacob Carlborg (8/13) Jan 22 2013 I watched a talk about AST macros in Scala. He said it was a fairly
- Philippe Sigaud (4/9) Jan 21 2013 Would any of you be so kind as to propose another definition for AST
- deadalnix (4/20) Jan 21 2013 Well, AST macro don't exists in D, so it will probably be subject
- Max Samukha (3/19) Jan 22 2013 AST macros is CTFE done right :)
- deadalnix (2/24) Jan 22 2013 That is completely nonsensial.
- Andrei Alexandrescu (4/20) Jan 22 2013 Not at all, I'd say. CTFE has a much lower cost of learning - you only
- Jacob Carlborg (16/18) Jan 22 2013 To be able to use AST macros one needs CTFE. One needs functions to
- Andrei Alexandrescu (9/25) Jan 22 2013 Martin Odersky confessed to me being quite worried about the possible
- deadalnix (27/35) Jan 23 2013 Can he or you explain why ?
- H. S. Teoh (14/20) Jan 23 2013 Yeah, as I said elsewhere in this forum, D tends to work wonderfully
- John Colvin (7/31) Jan 23 2013 D is already so feature rich. As cool as all these ideas are, at
- Russel Winder (24/31) Jan 23 2013 AST transforms are working wonderfully well in Groovy. This is the tool
- Andrei Alexandrescu (4/8) Jan 23 2013 Given the richness of today's D, I'd say AST macros are not part of the
- Russel Winder (22/24) Jan 23 2013 =20
- Araq (1/8) Jan 23 2013 There is also Nimrod which has 'yield' and AST macros ...
- Jacob Carlborg (5/6) Jan 23 2013 And Nemerle (on .Net), which both has AST macros and allows the
- Rob T (14/16) Jan 23 2013 On Wednesday, 23 January 2013 at 21:13:12 UTC, Russel Winder
- Jacob Carlborg (11/15) Jan 23 2013 I was talking about functions running at compile time. In D that's
- Andrei Alexandrescu (9/24) Jan 23 2013 To the smallest extent possible.
- deadalnix (3/10) Jan 23 2013 SDC does something similar with LLVM JIT capabilities.
- Jacob Carlborg (4/5) Jan 23 2013 That's the correct approach.
- David Nadlinger (11/14) Jan 24 2013 The question is not so much about correctness, but about
- deadalnix (7/22) Jan 24 2013 This is what SDC does currently, but yes, simple constant folding
- Jacob Carlborg (13/22) Jan 23 2013 Of course. But then the CTFE and regular code is handled differently by
- H. S. Teoh (28/42) Jan 21 2013 I don't think anyone has defined what "AST macros" are supposed to be
- Timon Gehr (4/9) Jan 22 2013 Why not? I have essentially done it and posted it here.
- Rob T (8/11) Jan 20 2013 Where does the overhead come from? Is the overhead from using
- Nick Sabalausky (16/29) Jan 21 2013 Real fibers have their own call stacks, so creating them and switching
- Rob T (11/29) Jan 21 2013 I have not yet had time to actually use fibers for anything real,
- Nick Sabalausky (112/146) Jan 21 2013 Their usage, yes, and that does make it a very enticing prospect. And
- deadalnix (8/40) Jan 21 2013 It has no chance to be as fast. However, I use them quite a lot
The author of the experimental language Magpie is very intelligent (in past I have read a very nice blog post about the unusual bootstrapped type system of Magpie). Here he nicely discusses well known things: http://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/ Reddit thread: http://www.reddit.com/r/programming/comments/16ja3f/iteration_inside_and_out/ A person on Reddit ("munificent", I think the blog post author himself) says that Magpie uses fibers to solve that dilemma, to be seen in a successive post. In D the Range static protocol of iteration is external and opApply is internal. Some persons have suggested to use fibers in D to introduce a very handy "yield" syntax for internal iteration. I think similarly short but clear article, about D Ranges and opApply should be added in the articles (http://dlang.org/articles.html ) section of the D site. Bye, bearophile
Jan 15 2013
On Jan 15, 2013, at 4:52 AM, bearophile <bearophileHUGS lycos.com> = wrote:The author of the experimental language Magpie is very intelligent (in =past I have read a very nice blog post about the unusual bootstrapped = type system of Magpie). Here he nicely discusses well known things:=20 http://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/ =20 Reddit thread: =http://www.reddit.com/r/programming/comments/16ja3f/iteration_inside_and_o= ut/=20 A person on Reddit ("munificent", I think the blog post author =himself) says that Magpie uses fibers to solve that dilemma, to be seen = in a successive post.=20 In D the Range static protocol of iteration is external and opApply is =internal. Some persons have suggested to use fibers in D to introduce a = very handy "yield" syntax for internal iteration.=20 I think similarly short but clear article, about D Ranges and opApply =should be added in the articles (http://dlang.org/articles.html ) = section of the D site. Maybe someone could crib from Mikola's talk: http://vimeo.com/1873969=
Jan 15 2013
On Tue, 15 Jan 2013 13:52:10 +0100 "bearophile" <bearophileHUGS lycos.com> wrote:In D the Range static protocol of iteration is external and opApply is internal. Some persons have suggested to use fibers in D to introduce a very handy "yield" syntax for internal iteration.D has problems in this area, there's at least three ways to do it and yet all of them have major downsides: opApply: The result is NOT usable as a range; it's strictly foreach-only. Also: Unintuitive function signature, "yield" must become "mixin(yield...)", and you need to create a dummy struct for it to sit in. Fibers: Too much performance overhead to be a general solution. Only good for, as an example, heavily I/O-bound stuff. Custom Input Range: Technically amounts to a co-routine, but is created using an awkward event-loop style. The event-loop style is necessary for Bidirectional/Random-access/etc ranges to be possible, but this is an artificial constraint for input (and maybe even forward) ranges. Then there's C/C++ which has libs that offer what are known as "stackless fibers". These utilize the preprocessor, along with switch coroutines: It lets the user write a normal coroutine, with a normal yield, which then gets trivially rewritten behind-the-scenes into an event loop (with NO actual fibers involved). I'm not sure to what extent this would be possible in D. If it is, the lack of preprocessor versions. (Not that I'd want a preprocessor.) So what D really, REALLY needs (this is one of the top things on my wish list for a hypothetical D3) is real coroutine syntax which, much rewritten behind-the-scenes into a switch-based event loop, BUT this coroutine would actually count as an input range. tl;dr: D's input ranges are much more awkward to create than they actually NEED to be, but the existing workarounds all have big problems.I think similarly short but clear article, about D Ranges and opApply should be added in the articles (http://dlang.org/articles.html ) section of the D site. Bye, bearophile
Jan 18 2013
On 01/18/2013 06:59 PM, Nick Sabalausky wrote:.... tl;dr: D's input ranges are much more awkward to create than they actually NEED to be, but the existing workarounds all have big problems. ...My shot at it: http://dpaste.dzfl.pl/baa538af (Does not work with 2.061)
Jan 18 2013
On 01/19/13 03:14, Timon Gehr wrote:On 01/18/2013 06:59 PM, Nick Sabalausky wrote:What doesn't work? I took the examples from your code and wrote a "saner" pseudo-generator. It doesn't need to manipulate code as strings (that's reinventing the preprocessor), but still needs to be given the source as a string. Real Programmers don't use closures, so there's no real alternative. And the yield syntax is at least as unnatural as the opApply one that Nick was complaining about. But it's already usable, and a good starting point to figure out the missing sugar. Well, after ignoring all the compiler-problem workarounds in there. After writing this, I'm not touching a D compiler for a while... At least the result is as efficient as it gets (gdc has no problem optimizing simple generators away completely) which was the main goal, and likely wouldn't have been possible w/ closures. Maybe someone can figure out a saner 'yield' implementation - one which doesn't require a symbol. Code below. artur // Generator by Artur; Examples borrowed from Timon Gehr. auto iota(T)(T start, T end) { struct State { T start, end, i; }; // An anon struct as template parm would have been better, // but until D supports that, this is better than a mixin. return Generator!(State, q{ for (i=start; i<end; ++i) mixin(yield!(state.i)); }) (start, end); } auto map(alias F, T)(T src) { struct State { T r; alias F MF; }; return Generator!(State, q{ for(; !r.empty; r.popFront()) { auto y = MF(r.front); mixin(yield!y); } }) (src); } auto take(T, N)(T src, N num) { struct State { T r; N n; }; return Generator!(State, q{ while(n-- && !r.empty) { auto y = r.front; mixin(yield!y); r.popFront(); } }) (src, num); } auto cprod(A, B)(A a, B b) { struct State { A a; B b, t; import std.typecons : q = tuple; }; return Generator!(State, q{ for ( ; !a.empty; a.popFront()) for (t=b.save; !t.empty; t.popFront()) { auto r = q(a.front, t.front); mixin(yield!r); } }) (a, b); } struct Tree(T) { Tree* l, r; T v; this(T a) { v = a; } this(Tree* a, T b, Tree* c) { l = a; v = b; r = c; } } Tree!T* tree(T)(T a = T.init) { return new Tree!T(a); } Tree!T* tree(T)(Tree!T* a, T b, Tree!T* c=null) { return new Tree!T(a, b, c); } struct InOrder(T) { struct State { Tree!T* root; InOrder* subtree; }; mixin GeneratorT!(State, q{ if (root.l) static if (typeof(subtree).tupleof.length) { // Naughty compiler! for(subtree = new InOrder(root.l); !subtree.empty; subtree.popFront() ) { auto r = subtree.front; mixin(yield!r); } } auto r = root.v; mixin(yield!(r, 2)); if (root.r) static if (typeof(subtree).tupleof.length) { // Ditto. Hrm. if (!subtree) subtree = new InOrder(root.r); else { subtree.reset(); subtree.root = root.r; } for(; !subtree.empty; subtree.popFront() ) { auto r = subtree.front; mixin(yield!(r, 3)); } } if (subtree) { delete subtree; subtree = null; } }); this(A...)(A a) { setup(a); } } InOrder!T inorder(T)(Tree!T* tree) { return InOrder!T(tree); } void main() { static import std.conv; writeln(take(map!(std.conv.to!string)(iota(42, 2_000_000_000)), 10)); writeln(cprod([1,2,3], [1L,2])); writeln(inorder(tree(tree(tree!int(), 1, tree(3)), 12, tree(tree(2), 3, tree(2))))); } // Generator implementation: template yield(alias S, int N=1) { // Not exactly rvalue friendly by nature. // More than one 'yield' inside a function requires that all of them // (but one) are manually numbered. The compiler will catch any duplicates. enum string yield = "{" " this.lastYield = " ~ N.stringof ~ ";" " return " ~ S.stringof ~ ";" " case " ~ N.stringof ~ ": {} }\n"; } import std.array; struct Generator(STATE, string CODE) { mixin GeneratorT!(STATE,CODE); } mixin template GeneratorT(STATE, string CODE) { alias typeof(Hack!STATE.RetTypeFunc!CODE()) ET; ET elem; void reset() { lastYield = 0; } bool empty() property { if (!lastYield) elem = f(); return lastYield<0; } auto front() property { if (!lastYield) elem = f(); if (lastYield>=0) return elem; assert(0); } void popFront() { elem = f(); } STATE state; alias state this; this(A...)(A a) { setup(a); } void setup(A...)(A a) { state.tupleof[0..A.length] = a; } ET f() { switch (lastYield) { default: mixin(CODE); } lastYield = -1; return typeof(return).init; } } // This struct is only used to deduce the type for Generator's 'front', // The more obvious ways to do that fail because of either forward ref errors, or ICEs. struct Hack(STATE) { int lastYield; STATE state; alias state this; auto RetTypeFunc(string CODE)() { switch (lastYield) { default: mixin(CODE); } assert(0); } }.... tl;dr: D's input ranges are much more awkward to create than they actually NEED to be, but the existing workarounds all have big problems. ...My shot at it: http://dpaste.dzfl.pl/baa538af (Does not work with 2.061)
Jan 20 2013
On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Then there's C/C++ which has libs that offer what are known as "stackless fibers". These utilize the preprocessor, along with switch its coroutines: It lets the user write a normal coroutine, with a normal yield, which then gets trivially rewritten behind-the-scenes into an event loop (with NO actual fibers involved). I'm not sure to what extent this would be possible in D. If it is, the lack of preprocessor would probably make it much less nice-looking to use than the versions. (Not that I'd want a preprocessor.)Is this also known as protothreads? http://dunkels.com/adam/pt/
Jan 19 2013
On Sat, 19 Jan 2013 09:45:25 +0100 "qznc" <qznc go.to> wrote:On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Yea. In fact, that's the exact same lib I've used.Then there's C/C++ which has libs that offer what are known as "stackless fibers". These utilize the preprocessor, along with switch its coroutines: It lets the user write a normal coroutine, with a normal yield, which then gets trivially rewritten behind-the-scenes into an event loop (with NO actual fibers involved). I'm not sure to what extent this would be possible in D. If it is, the lack of preprocessor would probably make it much less nice-looking to use than the versions. (Not that I'd want a preprocessor.)Is this also known as protothreads? http://dunkels.com/adam/pt/
Jan 19 2013
On 01/19/2013 10:46 PM, Nick Sabalausky wrote:On Sat, 19 Jan 2013 09:45:25 +0100 "qznc" <qznc go.to> wrote:This can be implemented a lot better looking in D. (My quick hack already looks better.) But I think we should first build a general-purpose DSEL library.On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Yea. In fact, that's the exact same lib I've used.Then there's C/C++ which has libs that offer what are known as "stackless fibers". These utilize the preprocessor, along with switch its coroutines: It lets the user write a normal coroutine, with a normal yield, which then gets trivially rewritten behind-the-scenes into an event loop (with NO actual fibers involved). I'm not sure to what extent this would be possible in D. If it is, the lack of preprocessor would probably make it much less nice-looking to use than the versions. (Not that I'd want a preprocessor.)Is this also known as protothreads? http://dunkels.com/adam/pt/
Jan 19 2013
On Sun, Jan 20, 2013 at 3:45 AM, Timon Gehr <timon.gehr gmx.ch> wrote:But I think we should first build a general-purpose DSEL library.Almost there. I almost have macros, even. But the generated parser is still quite slow...
Jan 20 2013
On Sunday, 20 January 2013 at 02:45:01 UTC, Timon Gehr wrote:On 01/19/2013 10:46 PM, Nick Sabalausky wrote:DSEL ?On Sat, 19 Jan 2013 09:45:25 +0100 "qznc" <qznc go.to> wrote:This can be implemented a lot better looking in D. (My quick hack already looks better.) But I think we should first build a general-purpose DSEL library.On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Yea. In fact, that's the exact same lib I've used.Then there's C/C++ which has libs that offer what are known as "stackless fibers". These utilize the preprocessor, along with switch for its coroutines: It lets the user write a normal coroutine, with a normal yield, which then gets trivially rewritten behind-the-scenes into an event loop (with NO actual fibers involved). I'm not sure to what extent this would be possible in D. If it is, the lack of preprocessor would probably make it much less nice-looking to use than the versions. (Not that I'd want a preprocessor.)Is this also known as protothreads? http://dunkels.com/adam/pt/
Jan 20 2013
On Sun, Jan 20, 2013 at 5:27 PM, deadalnix <deadalnix gmail.com> wrote:Domain-Specific Embedded Language, I guess. Timon is just making a distinction between internal DSL (hence DSEL), that you 'embed' in your code and external DSL (like build files...) that are, well, in external files.This can be implemented a lot better looking in D. (My quick hack already looks better.) But I think we should first build a general-purpose DSEL library.DSEL ?
Jan 20 2013
On Sun, 20 Jan 2013 03:45:00 +0100 Timon Gehr <timon.gehr gmx.ch> wrote:On 01/19/2013 10:46 PM, Nick Sabalausky wrote:If we need to resort to using D-as-a-DSL-inside-D to get decent coroutines, then that just further proves the need for a real coroutine support in the language.On Sat, 19 Jan 2013 09:45:25 +0100 "qznc" <qznc go.to> wrote:This can be implemented a lot better looking in D. (My quick hack already looks better.) But I think we should first build a general-purpose DSEL library.On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Yea. In fact, that's the exact same lib I've used.Then there's C/C++ which has libs that offer what are known as "stackless fibers". These utilize the preprocessor, along with switch its coroutines: It lets the user write a normal coroutine, with a normal yield, which then gets trivially rewritten behind-the-scenes into an event loop (with NO actual fibers involved). I'm not sure to what extent this would be possible in D. If it is, the lack of preprocessor would probably make it much less nice-looking to use than the versions. (Not that I'd want a preprocessor.)Is this also known as protothreads? http://dunkels.com/adam/pt/
Jan 20 2013
On Sunday, 20 January 2013 at 20:19:56 UTC, Nick Sabalausky wrote:If we need to resort to using D-as-a-DSL-inside-D to get decent coroutines, then that just further proves the need for a real coroutine support in the language.A good part of the job is done with Fibers. The biggest problem I see is module constructor and switching from TLS to fiber local storage.
Jan 20 2013
On Mon, 21 Jan 2013 03:27:49 +0100 "deadalnix" <deadalnix gmail.com> wrote:On Sunday, 20 January 2013 at 20:19:56 UTC, Nick Sabalausky wrote:That's no good for general-purpose, then. Fibers may be light-weight compared to threads, but (as I learned when *I* made a fiber-based solution last year) fibers still have way to much overhead to be a *general-purpose* approach the the matter. For more info, see jerro's posts here: http://forum.dlang.org/thread/jno6o5$qtb$1 digitalmars.com So like I already said a few posts back, *ALL* the currently-possible solutions in D have issues: opApply: Not a range; awkward to use Manually-Created Input Range: Event-loop-style instead of procedural. Yuck. Real Fibers: Too slow to be general-purpose. Stackless "fibers": Requires gross syntactical contortions much like opApply does.If we need to resort to using D-as-a-DSL-inside-D to get decent coroutines, then that just further proves the need for a real coroutine support in the language.A good part of the job is done with Fibers. The biggest problem I see is module constructor and switching from TLS to fiber local storage.
Jan 21 2013
On Monday, 21 January 2013 at 08:27:28 UTC, Nick Sabalausky wrote:Stackless "fibers": Requires gross syntactical contortions much like opApply does.Can you explain more what a stackless fiber is ? From the linked posted above I did really understood, as the example code clearly call functions, which require stack.
Jan 21 2013
On 01/21/2013 10:08 AM, deadalnix wrote:On Monday, 21 January 2013 at 08:27:28 UTC, Nick Sabalausky wrote:A stackless fiber does not have the execution stack as part of its context. (Therefore it cannot yield from nested function calls.)Stackless "fibers": Requires gross syntactical contortions much like opApply does.Can you explain more what a stackless fiber is ? From the linked posted above I did really understood, as the example code clearly call functions, which require stack.
Jan 21 2013
On Monday, 21 January 2013 at 09:18:34 UTC, Timon Gehr wrote:On 01/21/2013 10:08 AM, deadalnix wrote:Ho yeah, I looked at the implementation. It is mostly made of macro that create a function with a big switch in it. Why can't this be done in D ? What are the major problems ?On Monday, 21 January 2013 at 08:27:28 UTC, Nick Sabalausky wrote:A stackless fiber does not have the execution stack as part of its context. (Therefore it cannot yield from nested function calls.)Stackless "fibers": Requires gross syntactical contortions much like opApply does.Can you explain more what a stackless fiber is ? From the linked posted above I did really understood, as the example code clearly call functions, which require stack.
Jan 21 2013
On Mon, 21 Jan 2013 11:48:58 +0100 "deadalnix" <deadalnix gmail.com> wrote:On Monday, 21 January 2013 at 09:18:34 UTC, Timon Gehr wrote:I don't know whether or not it can be done in D. But, if it can be done, it would definitely require awkward syntax. Probably more awkward than the preprocessor-based syntax of the C/C++ version. (Not that I want a preprocessor in D.) Maybe you could do it by sticking the whole coroutine into a string literal that gets ripped apart and reassembled by a CTFE D parser, but that would just be so clumsy and error-prone, and frankly far more complex than should really be necessary, that I'd call it more of a kludge than a solution. And really, if I have to write D code inside a string literal to use it, that alone indicates that we're looking down the wrong path.On 01/21/2013 10:08 AM, deadalnix wrote:Ho yeah, I looked at the implementation. It is mostly made of macro that create a function with a big switch in it. Why can't this be done in D ? What are the major problems ?On Monday, 21 January 2013 at 08:27:28 UTC, Nick Sabalausky wrote:A stackless fiber does not have the execution stack as part of its context. (Therefore it cannot yield from nested function calls.)Stackless "fibers": Requires gross syntactical contortions much like opApply does.Can you explain more what a stackless fiber is ? From the linked posted above I did really understood, as the example code clearly call functions, which require stack.
Jan 21 2013
On 2013-01-21 20:00, Nick Sabalausky wrote:I don't know whether or not it can be done in D. But, if it can be done, it would definitely require awkward syntax. Probably more awkward than the preprocessor-based syntax of the C/C++ version. (Not that I want a preprocessor in D.) Maybe you could do it by sticking the whole coroutine into a string literal that gets ripped apart and reassembled by a CTFE D parser, but that would just be so clumsy and error-prone, and frankly far more complex than should really be necessary, that I'd call it more of a kludge than a solution. And really, if I have to write D code inside a string literal to use it, that alone indicates that we're looking down the wrong path.I know people don't like it but I have to say, this seems it could be a job for AST macros. -- /Jacob Carlborg
Jan 21 2013
On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:I know people don't like it but I have to say, this seems it could be a job for AST macros.It would be just as ugly as C macros. Well maybe not as ugly, but D should have direct support for co-routines, it's an important feature with plenty of uses. BTW, has anyone in here has experience working with Simula? Co-routines as a language feature has been around for decades in a proven way. --rt
Jan 21 2013
On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:On 2013-01-21 20:00, Nick Sabalausky wrote:I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xDI don't know whether or not it can be done in D. But, if it can be done, it would definitely require awkward syntax. Probably more awkward than the preprocessor-based syntax of the C/C++ version. (Not that I want a preprocessor in D.) Maybe you could do it by sticking the whole coroutine into a string literal that gets ripped apart and reassembled by a CTFE D parser, but that would just be so clumsy and error-prone, and frankly far more complex than should really be necessary, that I'd call it more of a kludge than a solution. And really, if I have to write D code inside a string literal to use it, that alone indicates that we're looking down the wrong path.I know people don't like it but I have to say, this seems it could be a job for AST macros.
Jan 21 2013
"deadalnix" <deadalnix gmail.com> wrote in message news:zrmlbyboedaswcllzwgb forum.dlang.org...On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:On 2013-01-21 20:00, Nick Sabalausky wrote: I know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 21 2013
"deadalnix" <deadalnix gmail.com> wrote in message news:zrmlbyboedaswcllzwgb forum.dlang.org...On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:AST macros are just compiler support pushed into user code/libraries. Exposing the AST to the user is a huge task and forces any supporting compiler to use a fixed AST representation.On 2013-01-21 20:00, Nick Sabalausky wrote: I know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 21 2013
On 2013-01-22 04:43, Daniel Murphy wrote:AST macros are just compiler support pushed into user code/libraries. Exposing the AST to the user is a huge task and forces any supporting compiler to use a fixed AST representation.Would that be so bad idea, to have a fixed AST representation? The AST presented for the user doesn't need to be the same as the compiler uses internally. It's the same as any library function. You can easily change the implementation as long as the signature and behavior is the same. -- /Jacob Carlborg
Jan 21 2013
"Jacob Carlborg" <doob me.com> wrote in message news:kdlfhr$1676$1 digitalmars.com...Would that be so bad idea, to have a fixed AST representation? The AST presented for the user doesn't need to be the same as the compiler uses internally. It's the same as any library function. You can easily change the implementation as long as the signature and behavior is the same. -- /Jacob CarlborgIt depends how much information is in the AST you give the user. Just syntax? Types? Full semantic information? Of course you can transform the internal AST to the user AST, but the more information the closer this gets to forcing the compiler to use the user AST, or support two ASTs internally.
Jan 22 2013
On 2013-01-22 12:00, Daniel Murphy wrote:It depends how much information is in the AST you give the user. Just syntax? Types? Full semantic information? Of course you can transform the internal AST to the user AST, but the more information the closer this gets to forcing the compiler to use the user AST, or support two ASTs internally.I watched a talk about AST macros in Scala. He said it was a fairly small change to the compiler to implement. Around 1k lines of code. The AST introspection was already there in the form of runtime reflection. I don't expect it to be as easy to do in DMD. Although Don has said it would be pretty easy to expose the internal AST to the user. -- /Jacob Carlborg
Jan 22 2013
On Tue, Jan 22, 2013 at 2:55 AM, deadalnix <deadalnix gmail.com> wrote:On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:Would any of you be so kind as to propose another definition for AST macros here ? http://wiki.dlang.org/Commonly-Used_AcronymsI know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 21 2013
On Tuesday, 22 January 2013 at 05:51:16 UTC, Philippe Sigaud wrote:On Tue, Jan 22, 2013 at 2:55 AM, deadalnix <deadalnix gmail.com> wrote:Well, AST macro don't exists in D, so it will probably be subject to controversy, but let me add something here.On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:Would any of you be so kind as to propose another definition for AST macros here ? http://wiki.dlang.org/Commonly-Used_AcronymsI know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 21 2013
On Tuesday, 22 January 2013 at 05:51:16 UTC, Philippe Sigaud wrote:On Tue, Jan 22, 2013 at 2:55 AM, deadalnix <deadalnix gmail.com> wrote:AST macros is CTFE done right :)On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:Would any of you be so kind as to propose another definition for AST macros here ? http://wiki.dlang.org/Commonly-Used_AcronymsI know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 22 2013
On Tuesday, 22 January 2013 at 12:14:26 UTC, Max Samukha wrote:On Tuesday, 22 January 2013 at 05:51:16 UTC, Philippe Sigaud wrote:That is completely nonsensial.On Tue, Jan 22, 2013 at 2:55 AM, deadalnix <deadalnix gmail.com> wrote:AST macros is CTFE done right :)On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:Would any of you be so kind as to propose another definition for AST macros here ? http://wiki.dlang.org/Commonly-Used_AcronymsI know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 22 2013
On 1/22/13 7:14 AM, Max Samukha wrote:On Tuesday, 22 January 2013 at 05:51:16 UTC, Philippe Sigaud wrote:Not at all, I'd say. CTFE has a much lower cost of learning - you only need to know which subset of D is allowed. Maybe you meant code mixins? AndreiOn Tue, Jan 22, 2013 at 2:55 AM, deadalnix <deadalnix gmail.com> wrote:AST macros is CTFE done right :)On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:Would any of you be so kind as to propose another definition for AST macros here ? http://wiki.dlang.org/Commonly-Used_AcronymsI know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 22 2013
On 2013-01-22 20:51, Andrei Alexandrescu wrote:Not at all, I'd say. CTFE has a much lower cost of learning - you only need to know which subset of D is allowed. Maybe you meant code mixins?To be able to use AST macros one needs CTFE. One needs functions to manipulate the AST during compile time. As far as I understand it, in Scala they just create a new instance of the compiler, during compilation, and just like that they have access to the whole language during compilation. In D it feels like a feature first need to be implemented in the regular compiler. Then it needs to be duplicated to be able to be used as CTFE. Example, in Scala if you throw an exception during compile time it will be handled properly and generate a compile error. What happens if you do the same in D? It won't run the function during compile time? Techincally you can generate an empty AST just to be able to run a bunch of functions during compile time. This would be no higher cost of learning than CTFE in D. -- /Jacob Carlborg
Jan 22 2013
On 1/23/13 2:28 AM, Jacob Carlborg wrote:On 2013-01-22 20:51, Andrei Alexandrescu wrote:Martin Odersky confessed to me being quite worried about the possible community reaction to the introduction of AST macros. I haven't kept close tabs to see how it's turning out.Not at all, I'd say. CTFE has a much lower cost of learning - you only need to know which subset of D is allowed. Maybe you meant code mixins?To be able to use AST macros one needs CTFE. One needs functions to manipulate the AST during compile time. As far as I understand it, in Scala they just create a new instance of the compiler, during compilation, and just like that they have access to the whole language during compilation.In D it feels like a feature first need to be implemented in the regular compiler. Then it needs to be duplicated to be able to be used as CTFE. Example, in Scala if you throw an exception during compile time it will be handled properly and generate a compile error. What happens if you do the same in D? It won't run the function during compile time? Techincally you can generate an empty AST just to be able to run a bunch of functions during compile time. This would be no higher cost of learning than CTFE in D.I completely disagree. (Sorry to foul you twice.) All AST macro systems I've studied are considerably difficult to understand and use effectively. By comparison, string macros are brutal and unstructured but the kind of thing all programmer worth their salt can get done. Andrei
Jan 22 2013
On Wednesday, 23 January 2013 at 07:57:10 UTC, Andrei Alexandrescu wrote:Martin Odersky confessed to me being quite worried about the possible community reaction to the introduction of AST macros. I haven't kept close tabs to see how it's turning out.Can he or you explain why ?I completely disagree. (Sorry to foul you twice.) All AST macro systems I've studied are considerably difficult to understand and use effectively. By comparison, string macros are brutal and unstructured but the kind of thing all programmer worth their salt can get done.2 things here. First, that is why people used to say about templates. D shows that this isn't a fatality. Secondly, this is true that AST macro is probably harder to understand. In fact, it is not expected that most programmer use it (or at least not before I'm retired as a dev). I don't even think any experienced dev should use it on a daily basis. However, it opens so much doors. First, no need for a custom compiler to test new features. Anyone can download source code and start using some new features. We can actually integrate field tested stuff in the language. Every D compiler can get the new feature as well. If a feature is controversial, I can include in in my project, but not in D in general. An example of such new feature is the iteration mechanism proposed here. However, I do think that attribute was a key piece for such mechanism, and has been handled the most backward possible way. So clean AST macro may have been impaired here. Anyway, I do strongly feel like we should stop adding more stuff now. Too much stuff is here already, some already start to misbehave together. It is probably time to consolidate the language, and keep that kind of stuff for a later version. After all, many language live without most of the feature D have.
Jan 23 2013
On Wed, Jan 23, 2013 at 09:38:01AM +0100, deadalnix wrote: [...]Anyway, I do strongly feel like we should stop adding more stuff now. Too much stuff is here already, some already start to misbehave together. It is probably time to consolidate the language, and keep that kind of stuff for a later version. After all, many language live without most of the feature D have.Yeah, as I said elsewhere in this forum, D tends to work wonderfully well when features are used in isolation, but once you start combining them, you quickly tread into unexplored territory, compiler holes, etc.. It's fun and cool to add new features, I'll agree, but it's really time for us to focus on using what we already have and iron out all the wrinkles so that we can have a product that we are proud of. T -- "No, John. I want formats that are actually useful, rather than over-featured megaliths that address all questions by piling on ridiculous internal links in forms which are hideously over-complex." -- Simon St. Laurent on xml-dev
Jan 23 2013
On Wednesday, 23 January 2013 at 15:36:16 UTC, H. S. Teoh wrote:On Wed, Jan 23, 2013 at 09:38:01AM +0100, deadalnix wrote: [...]D is already so feature rich. As cool as all these ideas are, at this stage it's hardly a priority. Also, having a high feature introduction rate with a low usage rate means that we lose the benefit of the practical hindsight that has provided so much useful information thus far (from c++, c, java etc.)Anyway, I do strongly feel like we should stop adding more stuff now. Too much stuff is here already, some already start to misbehave together. It is probably time to consolidate the language, and keep that kind of stuff for a later version. After all, many language live without most of the feature D have.Yeah, as I said elsewhere in this forum, D tends to work wonderfully well when features are used in isolation, but once you start combining them, you quickly tread into unexplored territory, compiler holes, etc.. It's fun and cool to add new features, I'll agree, but it's really time for us to focus on using what we already have and iron out all the wrinkles so that we can have a product that we are proud of. T
Jan 23 2013
On Wed, 2013-01-23 at 02:57 -0500, Andrei Alexandrescu wrote: [=E2=80=A6]Martin Odersky confessed to me being quite worried about the possible=20 community reaction to the introduction of AST macros. I haven't kept=20 close tabs to see how it's turning out.AST transforms are working wonderfully well in Groovy. This is the tool that is allowing there to be static type checking and static compilation of Groovy code amongst a whole load of other things. Macros in Scala are a bit more of a mixed blessing, not because they are not a useful tool but because of the reaction of the community. All in all I suspect they will be fine. [=E2=80=A6]I completely disagree. (Sorry to foul you twice.) All AST macro systems==20I've studied are considerably difficult to understand and use=20 effectively. By comparison, string macros are brutal and unstructured=20 but the kind of thing all programmer worth their salt can get done.There is no doubt that AST transforms in Groovy is not something the application programmer would spend time on unless they knew what they were doing. It isn't a trivial API. However it is straightforward once you know ASTs. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jan 23 2013
On 1/23/13 2:08 PM, Russel Winder wrote:There is no doubt that AST transforms in Groovy is not something the application programmer would spend time on unless they knew what they were doing. It isn't a trivial API. However it is straightforward once you know ASTs.Given the richness of today's D, I'd say AST macros are not part of the mythical plan. Andrei
Jan 23 2013
On Wed, 2013-01-23 at 15:15 -0500, Andrei Alexandrescu wrote: [=E2=80=A6]Given the richness of today's D, I'd say AST macros are not part of the==20mythical plan.Works for me. The issue is only whether there is an idiomatic expression for a given style. For me currently D has everything I need that C++ makes difficult. The difficult tension for me is JVM vs. native. On the JVM I have Groovy, Scala, (Ceylon, Kotlin, JRuby, Jython, Clojure), even Java, which is an interesting milieu. Natively there is C, C++, D, Clay, Rust, Haskell which makes for fun tensions. The core problem is how to make D appealing to C and C++ programmers. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jan 23 2013
The difficult tension for me is JVM vs. native. On the JVM I have Groovy, Scala, (Ceylon, Kotlin, JRuby, Jython, Clojure), even Java, which is an interesting milieu. Natively there is C, C++, D, Clay, Rust, Haskell which makes for fun tensions.There is also Nimrod which has 'yield' and AST macros ...
Jan 23 2013
On 2013-01-24 01:30, Araq wrote:There is also Nimrod which has 'yield' and AST macros ...And Nemerle (on .Net), which both has AST macros and allows the programmer to add new syntax for these macros. -- /Jacob Carlborg
Jan 23 2013
On Wednesday, 23 January 2013 at 21:13:12 UTC, Russel Winder wrote: [...]The core problem is how to make D appealing to C and C++ programmers.One possibility is that once we have 100% shared library support, C/C++ programmers can start making use out of a growing base of very nice libraries written in D that are also made compatible (to a degree) with C/C++. That's a potential ice breaker IMO, esp when C/C++ programmers discover that they will get much more functionality if they ditched C/C++ and used these libs with native D applications instead. This method of conversion to D a relatively safe and simple migration path. --rt
Jan 23 2013
On 2013-01-23 08:57, Andrei Alexandrescu wrote:I completely disagree. (Sorry to foul you twice.) All AST macro systems I've studied are considerably difficult to understand and use effectively. By comparison, string macros are brutal and unstructured but the kind of thing all programmer worth their salt can get done.I was talking about functions running at compile time. In D that's handled by an interpreter which doesn't support the full language. It also behaves differently from the "regular" language. Bugs occur in the CTFE interpreter which doesn't occur in the regular compiler. In Scala it _is_ the regular compiler that handles both the CTFE and the regular code. A bug in the regular compiler will show up during CTFE as well. BTW, how do you make a string mixin hygienic? -- /Jacob Carlborg
Jan 23 2013
On 1/23/13 3:29 PM, Jacob Carlborg wrote:On 2013-01-23 08:57, Andrei Alexandrescu wrote:It's a subset. That's a better thing than _another_ language.I completely disagree. (Sorry to foul you twice.) All AST macro systems I've studied are considerably difficult to understand and use effectively. By comparison, string macros are brutal and unstructured but the kind of thing all programmer worth their salt can get done.I was talking about functions running at compile time. In D that's handled by an interpreter which doesn't support the full language.It also behaves differently from the "regular" language.To the smallest extent possible.Bugs occur in the CTFE interpreter which doesn't occur in the regular compiler.Not an argument.In Scala it _is_ the regular compiler that handles both the CTFE and the regular code. A bug in the regular compiler will show up during CTFE as well.Agreed this is a good thing for Scala, it takes advantage of the jit infrastructure.BTW, how do you make a string mixin hygienic?By passing fresh names as arguments into the function creating it. We don't have a strong story there. Andrei
Jan 23 2013
On Wednesday, 23 January 2013 at 21:50:39 UTC, Andrei Alexandrescu wrote:SDC does something similar with LLVM JIT capabilities.In Scala it _is_ the regular compiler that handles both the CTFE and the regular code. A bug in the regular compiler will show up during CTFE as well.Agreed this is a good thing for Scala, it takes advantage of the jit infrastructure.
Jan 23 2013
On 2013-01-24 03:35, deadalnix wrote:SDC does something similar with LLVM JIT capabilities.That's the correct approach. -- /Jacob Carlborg
Jan 23 2013
On Thursday, 24 January 2013 at 07:55:37 UTC, Jacob Carlborg wrote:On 2013-01-24 03:35, deadalnix wrote:The question is not so much about correctness, but about performance. Building an LLVM function and JIT-compiling it every time you need to evaluate a D expression will completely ruin your compile times (and I say that as an LLVM proponent). The idea itself is interesting for computationally heavy CTFE code, but I don't think it is feasible to go without lightweight code at least for simple »constant folding«-type applications. DavidSDC does something similar with LLVM JIT capabilities.That's the correct approach.
Jan 24 2013
On Thursday, 24 January 2013 at 13:59:43 UTC, David Nadlinger wrote:On Thursday, 24 January 2013 at 07:55:37 UTC, Jacob Carlborg wrote:This is what SDC does currently, but yes, simple constant folding should avoid doing that. But 1/ make it work and 2/ make it fast. Current implementation permit easily to add constant folding later.On 2013-01-24 03:35, deadalnix wrote:The question is not so much about correctness, but about performance. Building an LLVM function and JIT-compiling it every time you need to evaluate a D expression will completely ruin your compile times (and I say that as an LLVM proponent). The idea itself is interesting for computationally heavy CTFE code, but I don't think it is feasible to go without lightweight code at least for simple »constant folding«-type applications.SDC does something similar with LLVM JIT capabilities.That's the correct approach.
Jan 24 2013
On 2013-01-23 22:50, Andrei Alexandrescu wrote:It's a subset. That's a better thing than _another_ language.Of course. But then the CTFE and regular code is handled differently by the compiler it will start to become a different language, although very similar. I'm wondering if that is even worse.Not an argument.The argument is that it's not code to have two different parts of the compiler handling this.Exactly, that's what I'm trying to say.In Scala it _is_ the regular compiler that handles both the CTFE and the regular code. A bug in the regular compiler will show up during CTFE as well.Agreed this is a good thing for Scala, it takes advantage of the jit infrastructure.By passing fresh names as arguments into the function creating it. We don't have a strong story there.The function cannot then generate a symbol that is only used internally as a helper without breaking the hygienicy (or what it's called). You don't want the user to pass in names for symbols it doesn't know about, doesn't care about and should not know about. -- /Jacob Carlborg
Jan 23 2013
On Tue, Jan 22, 2013 at 06:51:07AM +0100, Philippe Sigaud wrote:On Tue, Jan 22, 2013 at 2:55 AM, deadalnix <deadalnix gmail.com> wrote:I don't think anyone has defined what "AST macros" are supposed to be yet. There have been some vague ideas thrown about, but nothing is concrete AFAIK. For one thing, it's not even clear how said "AST macros" are supposed to work, or what they're supposed to do. Do they perform *arbitrary* transformations from some given AST subtree into another? (Arbitrary, as in, you can implement an "in-library" optimizer that substitutes inefficient subtrees with optimized versions, or even a codegen that transforms AST trees into a linear form that maps directly to IR or machine code.) Or is it something simpler and more within our reach, something like the C preprocessor but operating on AST subtrees instead of tokens (as in, a macro is called with some AST tree fragments as parameters, which get grafted into the macro body's AST at certain points)? Or is it something else altogether, like some kind of compile-time introspection that allows you to access and modify node attributes in the parsed AST of the code in some way, so that you change the way it's compiled? Until this is pinned down, "AST macros" can virtually be *anything*. It has been said that they can solve all kinds of problems in D, including the halting problem, world peace, and world hunger, and can be used to construct all manner of amazing features like writing your code for you, implementing an oracle machine, etc.. But nobody even knows what they are or how they're supposed to work. T -- Freedom: (n.) Man's self-given right to be enslaved by his own depravity.On Monday, 21 January 2013 at 19:23:19 UTC, Jacob Carlborg wrote:Would any of you be so kind as to propose another definition for AST macros here ? http://wiki.dlang.org/Commonly-Used_AcronymsI know people don't like it but I have to say, this seems it could be a job for AST macros.I was thinking the same thing, but don't wanted to bug people. Indeed, it is the perfect job for AST macro. I can concur now that you mentioned it xD
Jan 21 2013
On 01/21/2013 08:00 PM, Nick Sabalausky wrote:On Mon, 21 Jan 2013 11:48:58 +0100 "deadalnix" <deadalnix gmail.com> wrote: ...Why not? I have essentially done it and posted it here. Also, there is nothing feasible that 'cannot be done' in D, because D can host arbitrarily complex embedded languages.Why can't this be done in D ? What are the major problems ?I don't know whether or not it can be done in D. ...
Jan 22 2013
On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Fibers: Too much performance overhead to be a general solution. Only good for, as an example, heavily I/O-bound stuff.Where does the overhead come from? Is the overhead from using fibers the only problem for implementing coroutines? I ask, because if except for the overhead, fibers are a good general solution, then it makes sense to determine if anything can be done to lessen the overhead before trying to implement yet another solution. --rt
Jan 20 2013
On Mon, 21 Jan 2013 01:18:48 +0100 "Rob T" <alanb ucora.com> wrote:On Friday, 18 January 2013 at 17:59:36 UTC, Nick Sabalausky wrote:Real fibers have their own call stacks, so creating them and switching contexts between them on every iteration can never be made as fast as a simple for-loop or event-loop (both of which are computationally trivial). Stackless "fibers" OTOH can do this easily since they literally *are* trivial switch-driven event-loops under the hood, but just written in a cleaner way.Fibers: Too much performance overhead to be a general solution. Only good for, as an example, heavily I/O-bound stuff.Where does the overhead come from? Is the overhead from using fibers the only problem for implementing coroutines?I ask, because if except for the overhead, fibers are a good general solution, then it makes sense to determine if anything can be done to lessen the overhead before trying to implement yet another solution.Yea, they *would* be a good general solution, and I'm sure the overhead can be decreased, but AIUI I don't think it's even theoretically possible for them to optimized enough to compete with any of the other approaches as a general-purpose thing. The other stuff can be optimized down as far as being little more than an increment per iteration. But AIUI, using a real fiber would require two context-switches per iteration, so I'm not sure that can ever compete.
Jan 21 2013
On Monday, 21 January 2013 at 08:44:10 UTC, Nick Sabalausky wrote:I have not yet had time to actually use fibers for anything real, but I did play around with them and the usage seemed to be exactly what we're looking for to implement co-routines. Since you have experience using them for real, do you think they are useful in general assuming that the performance can be made par with the stackless select switch method? By chance, do you know if the current implementation is a built-in language feature or if it's implemented entirely as a library? --rtI ask, because if except for the overhead, fibers are a good general solution, then it makes sense to determine if anything can be done to lessen the overhead before trying to implement yet another solution.Yea, they *would* be a good general solution, and I'm sure the overhead can be decreased, but AIUI I don't think it's even theoretically possible for them to optimized enough to compete with any of the other approaches as a general-purpose thing. The other stuff can be optimized down as far as being little more than an increment per iteration. But AIUI, using a real fiber would require two context-switches per iteration, so I'm not sure that can ever compete.
Jan 21 2013
On Mon, 21 Jan 2013 21:15:48 +0100 "Rob T" <alanb ucora.com> wrote:On Monday, 21 January 2013 at 08:44:10 UTC, Nick Sabalausky wrote:Their usage, yes, and that does make it a very enticing prospect. And they are indeed fantastic for many things. But as soon as you start using them to implement something like: coroutine int myCoroutine() { yield 10; yield 20; if(blah) yield 30; foreach(i; arr) yield i; //etc } In other words, exactly the sorts of use-cases that coroutines are perfectly suited for. Then you have to consider that your coroutine may get used for anything from: foreach(i; myCoroutine) { string result = curl("http://example.com/"~to!string(i)); writeFile(to!string(i)~".txt", result); } to things like: int sum = myCoroutine.reduce!"a+b"(); The first case, with the I/O, is perfectly fine even if the coroutine operates using fibers. But the second example, as sleek and deceptively appealing as it looks, would have very poor performance because it's doing a ton of context switching even though all it *really* needs to do is grab a bunch of ints and add them. OTOH, *both* examples would be perfectly fine if the coroutine were trivially rewritten behind-the-scenes into a stackless event-loop that *didn't* use fibers: struct myCoroutine_localVars { int state=0; // Simulate the instruction pointer int i; // The foreach loop variable } enum IsDone {Yes, No} IsDone myCoroutine(ref myCoroutine_localVars context, ref int yieldValue) { switch(context.state) { case 0: context.state = 1; yieldValue = 10; return IsDone.No; // yield 10 case 1: context.state = 2; yieldValue = 20; return IsDone.No; // yield 20 case 2: if(blah) { context.state = 3; yieldValue = 30; return IsDone.No; // yield 30; } context.state = 3; goto case 3: case 3: context.i = 0; // Start for loop context.state = 4; goto case 4: case 4: if(context.i < arr.length) { context.i++; yieldValue = arr[context.i - 1]; return IsDone.No; // yield i } context.state = 5; goto case 5: case 5: return IsDone.Yes; } } // foreach(val; myCoroutine) {...stuff...} // becomes --> myCoroutine_localVars context; int yieldValue; while(myCoroutine(context, yieldValue) == IsDone.No) { int val = yieldValue; ...stuff... } Note that looks similar to an equivalent hand-written input range. So you'd have the performance of an input range in *all* situations, while still having the convenience of coroutine syntax. (My that's how C/C++'s protothreads work.) Note that transformation can be easily automated since C/C++'s protothreads does exactly that using nothing more than some very simple preprocessor macros. Real fibers are enticing as an easy way to implement coroutines, but once implemented, the only thing fibers would really accomplish here is to slow things down for certain use-cases. Well, also, real fibers would allow yielding from a function called by myCoroutine. But even without fibers there are ways to get around that limitation (as demonstrated by C/C++'s protothreads library).I have not yet had time to actually use fibers for anything real, but I did play around with them and the usage seemed to be exactly what we're looking for to implement co-routines.I ask, because if except for the overhead, fibers are a good general solution, then it makes sense to determine if anything can be done to lessen the overhead before trying to implement yet another solution.Yea, they *would* be a good general solution, and I'm sure the overhead can be decreased, but AIUI I don't think it's even theoretically possible for them to optimized enough to compete with any of the other approaches as a general-purpose thing. The other stuff can be optimized down as far as being little more than an increment per iteration. But AIUI, using a real fiber would require two context-switches per iteration, so I'm not sure that can ever compete.Since you have experience using them for real, do you think they are useful in general assuming that the performance can be made par with the stackless select switch method?If they could, then yes, but I don't believe that's a realistic possibility. (Others can correct me if I'm wrong, but I'm fairly sure.)By chance, do you know if the current implementation is a built-in language feature or if it's implemented entirely as a library?In short, I don't know. Others could answer better. In long: I *think* they're implemented in druntime, or at least their core functionality anyway. I don't know whether or not the druntime implementation relies on any special compiler support. Others can probably answer that. I do know that D's fibers don't use the OS-provided fibers (at least on Windows) since, at least on Windows, the OS fibers are generally considered to not be very fast or good.
Jan 21 2013
On Monday, 21 January 2013 at 20:15:49 UTC, Rob T wrote:On Monday, 21 January 2013 at 08:44:10 UTC, Nick Sabalausky wrote:It has no chance to be as fast. However, I use them quite a lot and they are very useful. Especially to hide IO latency or for dependancy management. I use them for the latter, some other software (like vide.d) use them for the former. This cannot be achieved with stackless coroutine method as you need to yield from anywhere, not only the root function.I have not yet had time to actually use fibers for anything real, but I did play around with them and the usage seemed to be exactly what we're looking for to implement co-routines. Since you have experience using them for real, do you think they are useful in general assuming that the performance can be made par with the stackless select switch method?I ask, because if except for the overhead, fibers are a good general solution, then it makes sense to determine if anything can be done to lessen the overhead before trying to implement yet another solution.Yea, they *would* be a good general solution, and I'm sure the overhead can be decreased, but AIUI I don't think it's even theoretically possible for them to optimized enough to compete with any of the other approaches as a general-purpose thing. The other stuff can be optimized down as far as being little more than an increment per iteration. But AIUI, using a real fiber would require two context-switches per iteration, so I'm not sure that can ever compete.By chance, do you know if the current implementation is a built-in language feature or if it's implemented entirely as a library?This is done as library right now, which is awesome !
Jan 21 2013