digitalmars.D - How Nested Functions Work, part 1
- Walter Bright (1/1) Aug 30 2009 http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_...
- Jeremie Pelletier (21/22) Aug 30 2009 I really like the way nested functions and closures are done in D. Espec...
- Jarrett Billingsley (10/21) Aug 30 2009 work_part_1/
- Jeremie Pelletier (4/25) Aug 30 2009 I need to try that out, its most likely a bug since 'in' means 'const sc...
- Jarrett Billingsley (13/16) Aug 30 2009 pe' now.
- Walter Bright (1/1) Aug 30 2009 That's very nice, could you post that on reddit?
- Jeremie Pelletier (3/4) Aug 31 2009 Just did, I even changed "D" to "the D programming language" because I k...
- Walter Bright (1/1) Aug 31 2009 Thanks!
- Jarrett Billingsley (5/6) Aug 31 2009 I don't mean to pull a Stewart, but please be sure to quote a bit of
- Andrei Alexandrescu (5/13) Aug 31 2009 Same happened to me, but I've been brought back to order by others who
- Bill Baxter (4/18) Aug 31 2009 Some of us read the NG via email, not a newsreader.
- Walter Bright (2/3) Aug 31 2009 Thunderbird email has an option to view emails in a threaded form.
- Adam D. Ruppe (10/13) Aug 31 2009 My email client (mutt) can do threading on it too. You might want to che...
- Bill Baxter (5/10) Aug 31 2009 I don't think gmail can do that.
- Walter Bright (3/6) Aug 31 2009 I try to counterbalance the person(s) who quote a 90 line message and
- Manfred_Nowak (4/5) Sep 01 2009 [...]
- Jeremie Pelletier (2/17) Aug 31 2009 Am I the only one here using web-news?
- Jarrett Billingsley (2/19) Aug 31 2009 Probably. It's full of fail.
- Bill Baxter (4/21) Aug 31 2009 Most people give up on the web-news interface after a week or two, if
- Jarrett Billingsley (3/17) Aug 31 2009 I said I'm using the mailing lists ;)
- Tim M (2/3) Aug 31 2009 Have had a quick look through. You could have explained that D supports ...
- Steven Schveighoffer (6/7) Aug 31 2009 Am I missing something or did you repeat the "Let's rewrite abc and def ...
- Walter Bright (2/5) Aug 31 2009 Eh, you're right.
- language_fan (10/11) Aug 31 2009 how_nested_functions_work_part_1/
- Walter Bright (12/21) Aug 31 2009 But not C, C++, Java, etc., so quite a lot of programmers have little
- language_fan (8/36) Aug 31 2009 Most programmers I know don't use those languages, but then again I'm
- Walter Bright (3/6) Aug 31 2009 That's actually not a bug. In function scopes, you can't reference a
- Jeremie Pelletier (5/12) Aug 31 2009 You have to agree however that this is counter-intuitive, since function...
- Walter Bright (3/3) Aug 31 2009 I agree it would be better to allow forward references for nested
- language_fan (3/6) Sep 02 2009 That's great news actually. It might even mean that this might change
- Michiel Helvensteijn (6/12) Sep 02 2009 I still find it silly that it was built that way. Seems to me you should...
- language_fan (13/26) Sep 02 2009 While the syntax might vary a bit in functional languages, it's a common...
- Rainer Deyke (6/9) Sep 02 2009 That can lead to subtle problems in the case of functions:
- Michiel Helvensteijn (6/15) Sep 02 2009 You're right, I forgot about that. You can conservatively statically for...
- Don (10/25) Sep 02 2009 I can't see how it can be done in the general case, other than by
- Jarrett Billingsley (7/35) Sep 02 2009 It wouldn't even be that difficult. Basically if you treat
- Michiel Helvensteijn (7/13) Sep 02 2009 That's what I meant, yes.
- Michiel Helvensteijn (5/9) Sep 02 2009 Oh, you may also not take a delegate of the function before i is declare...
- Jeremie Pelletier (5/34) Aug 31 2009 I agree with Walter here. While D is not the first place I see closures ...
- language_fan (6/16) Sep 02 2009 I can see your point. I have previously mostly used OCaml, Mercury,
- bearophile (15/16) Sep 02 2009 I may like this one:
- bearophile (11/11) Sep 02 2009 If the loop index "i" isn't necessary, you can use simpler code:
- Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= (23/68) Sep 02 2009 Also keep in mind that to increase confusion, D still supports the old s...
- Jarrett Billingsley (10/24) Sep 02 2009 Only valid one! I've been doing this too long ;)
- Andrei Alexandrescu (3/9) Sep 02 2009 Did someone file a bug report on this?
- Jarrett Billingsley (6/15) Sep 02 2009 Surprisingly, it doesn't seem like it. Walter himself, in the spec,
- Edward Diener (10/25) Sep 02 2009 I suggested this a long time back on this NG, and I am sure many others
- Andrei Alexandrescu (6/32) Sep 03 2009 IMHO it's ok if there are two types, as long as function is implicitly
- Edward Diener (23/56) Sep 03 2009 Good point ! That would be fine also. The basic issue is to allow a
- Jarrett Billingsley (5/10) Sep 03 2009 There's no real reason to get rid of function pointers. What type
- grauzone (16/27) Sep 03 2009 Probably the same type as .ptr?
- Jarrett Billingsley (8/22) Sep 03 2009 Yeah. There probably needs to be an extern(this) or so for functions
- Andrei Alexandrescu (7/68) Sep 03 2009 Actually it could be said that C++'s exercise with pointers to member
- Andrei Alexandrescu (7/68) Sep 03 2009 Actually it could be said that C++'s exercise with pointers to member
- Edward Diener (14/85) Sep 03 2009 Why do you think pointer to member function was a "departure from C++'s
- Andrei Alexandrescu (11/98) Sep 03 2009 Don't pay for what you don't use, low-key approach to under-the-wraps
- Don (11/94) Sep 04 2009 No kidding. When writing my "Member function pointers" CodeProject
- Edward Diener (14/119) Sep 04 2009 Hooking an object to a C++ pointer to member functions is not really
- Daniel Keep (7/13) Sep 02 2009 The problem is that function pointers and delegates have different
- Jarrett Billingsley (55/68) Sep 02 2009 Which is why I suggest that the ABI be changed ;) I suppose one method
- Daniel Keep (6/54) Sep 02 2009 You and me both. That said, this code is ported from an experimental
- Jeremie Pelletier (8/49) Sep 02 2009 The only valid syntax is up there, and you could use a simple closure in...
- Jarrett Billingsley (5/13) Sep 02 2009 n
- Tom S (8/16) Aug 31 2009 Some universities don't even have compiler classes. Mine only covered
- Daniel Keep (4/18) Aug 31 2009 Wollongong has a compiler course. They just never run it due to
- Michel Fortin (25/27) Sep 01 2009 true that C doesn't have nested functions, but Apple's version of C,
- Daniel Keep (16/29) Sep 01 2009 Oh sod blocks; the REAL awesome in that example is Grand Central
- Michel Fortin (19/28) Sep 01 2009 And they're dead easy to use. Want an asynchronous foreach loop on the
- Jeremie Pelletier (4/10) Sep 01 2009 The specification is overseen by the Khronos group, Apple was a major co...
- Michel Fortin (7/13) Sep 01 2009 I didn't say it was their work alone. What I meant is as you said: it
- Walter Bright (3/4) Sep 01 2009 Another thread on it!
http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/
Aug 30 2009
Walter Bright Wrote:http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/I really like the way nested functions and closures are done in D. Especially because they are the same thing as delegate and closures. But speaking of closures, I did notice something that could be optimized: void foo { int a; void foo2() { a++;} bar(&foo2); } void bar(in void delegate() dg) { dg(); } Here foo() is using _d_allocmemory to get storage for the stack frame. I understand it is for cases where the closure is executed long after the owner method has returned, but if the delegate has a scope storage class it could use the thread's stack instead. Using nested functions alone does use the stack for storage, unless you need to use a local delegate to fix forward references within nested functions resulting in _d_allocmemory allocating the stack frame, as in the following example: void myFoo() { int a; scope void delegate() bar = void; void foo() { bar(); } void foo2() { a++; if(a != 10) foo(); } bar = &foo2; foo(); } Closures in D is an amazing feature and I really miss it when I need to use another language (I can't find an employer who wants D code, but I keep my fingers crossed!), but here is yet another feature I try to avoid in time critical code right now because of the expensive call into the memory manager when I can write longer code that executes on stack storage. nice to know D beats its syntax, I would hate to have to assign delegates for every nested function!
Aug 30 2009
On Sun, Aug 30, 2009 at 9:00 PM, Jeremie Pelletier<jeremiep gmail.com> wrot= e:Walter Bright Wrote:work_part_1/http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_=I really like the way nested functions and closures are done in D. Especi=ally because they are the same thing as delegate and closures.But speaking of closures, I did notice something that could be optimized: void foo { =A0 =A0int a; =A0 =A0void foo2() { a++;} =A0 =A0bar(&foo2); } void bar(in void delegate() dg) { dg(); } Here foo() is using _d_allocmemory to get storage for the stack frame. I =understand it is for cases where the closure is executed long after the own= er method has returned, but if the delegate has a scope storage class it co= uld use the thread's stack instead. It already is optimized if you use "void bar(scope void delegate() dg)". If it doesn't optimize it when you use 'in', it's probably a bug. :)
Aug 30 2009
Jarrett Billingsley Wrote:On Sun, Aug 30, 2009 at 9:00 PM, Jeremie Pelletier<jeremiep gmail.com> wrote:I need to try that out, its most likely a bug since 'in' means 'const scope' now. Check my second code bit, the delegate is declared as scope and it doesn't optimize, maybe the compiler only checks if the closure is being dereferenced and if so switches to memory storage instead of stack storage without checking the storage class of the closure's delegate. And even without 'scope' in this case the compiler could detect that the delegate doesn't leave the function scope and optimize away. Better yet, allow forward references for nested functions. The need to assignWalter Bright Wrote:It already is optimized if you use "void bar(scope void delegate() dg)". If it doesn't optimize it when you use 'in', it's probably a bug. :)http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/I really like the way nested functions and closures are done in D. Especially because they are the same thing as delegate and closures. But speaking of closures, I did notice something that could be optimized: void foo { int a; void foo2() { a++;} bar(&foo2); } void bar(in void delegate() dg) { dg(); } Here foo() is using _d_allocmemory to get storage for the stack frame. I understand it is for cases where the closure is executed long after the owner method has returned, but if the delegate has a scope storage class it could use the thread's stack instead.
Aug 30 2009
On Sun, Aug 30, 2009 at 10:54 PM, Jeremie Pelletier<jeremiep gmail.com> wro= te:I need to try that out, its most likely a bug since 'in' means 'const sco=pe' now.Check my second code bit, the delegate is declared as scope and it doesn'=t optimize, maybe the compiler only checks if the closure is being derefere= nced and if so switches to memory storage instead of stack storage without = checking the storage class of the closure's delegate. And even without 'sco= pe' in this case the compiler could detect that the delegate doesn't leave = the function scope and optimize away. The compiler currently doesn't do anything with local delegates declared with 'scope'. It only seems to do anything special if 'scope' is used as a parameter storage class.Better yet, allow forward references for nested functions. The need to as=Oh indeed ;)
Aug 30 2009
That's very nice, could you post that on reddit?
Aug 30 2009
Walter Bright Wrote:That's very nice, could you post that on reddit?Just did, I even changed "D" to "the D programming language" because I know you like it for search engine referencing :) http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/c0cm3bk
Aug 31 2009
On Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Thanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
Jarrett Billingsley wrote:On Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. AndreiThanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
On Mon, Aug 31, 2009 at 1:11 PM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:Jarrett Billingsley wrote:Some of us read the NG via email, not a newsreader. --bbOn Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is.Thanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
Bill Baxter wrote:Some of us read the NG via email, not a newsreader.Thunderbird email has an option to view emails in a threaded form.
Aug 31 2009
On Mon, Aug 31, 2009 at 01:57:41PM -0700, Bill Baxter wrote:Some of us read the NG via email, not a newsreader.My email client (mutt) can do threading on it too. You might want to check the settings on your mail reader and see if you have a threading option - the necessary headers are in the messages. (That said, I agree that quoting the relevant part of messages is preferable, since I don't often use the threading mode and just read the messages as they come in.)--bb-- Adam D. Ruppe http://arsdnet.net
Aug 31 2009
On Mon, Aug 31, 2009 at 2:05 PM, Adam D. Ruppe<destructionator gmail.com> wrote:On Mon, Aug 31, 2009 at 01:57:41PM -0700, Bill Baxter wrote:I don't think gmail can do that. Anyway, pretty much Walter is the only one here who regularly writes replies with absolutely no context, so it's not a huge problem. --bbSome of us read the NG via email, not a newsreader.My email client (mutt) can do threading on it too. You might want to check the settings on your mail reader and see if you have a threading option - the necessary headers are in the messages.
Aug 31 2009
Bill Baxter wrote:I don't think gmail can do that. Anyway, pretty much Walter is the only one here who regularly writes replies with absolutely no context, so it's not a huge problem.I try to counterbalance the person(s) who quote a 90 line message and add a single sentence at the end!
Aug 31 2009
Walter Bright wrote:I try to[...] rofl :-) -manfred
Sep 01 2009
Andrei Alexandrescu Wrote:Jarrett Billingsley wrote:Am I the only one here using web-news?On Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. AndreiThanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
On Mon, Aug 31, 2009 at 6:30 PM, Jeremie Pelletier<jeremiep gmail.com> wrote:Andrei Alexandrescu Wrote:Probably. It's full of fail.Jarrett Billingsley wrote:Am I the only one here using web-news?On Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. AndreiThanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
On Mon, Aug 31, 2009 at 3:30 PM, Jeremie Pelletier<jeremiep gmail.com> wrote:Andrei Alexandrescu Wrote:Most people give up on the web-news interface after a week or two, if they intend to stick around for a while, at least. --bbJarrett Billingsley wrote:Am I the only one here using web-news?On Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is. AndreiThanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
On Mon, Aug 31, 2009 at 4:11 PM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:Jarrett Billingsley wrote:I said I'm using the mailing lists ;)On Mon, Aug 31, 2009 at 1:14 PM, Walter Bright<newshound1 digitalmars.com> wrote:Same happened to me, but I've been brought back to order by others who pointed out that turning "threaded" on in your newsreader clarifies what the parent message is.Thanks!I don't mean to pull a Stewart, but please be sure to quote a bit of the post you're responding to. If you don't, it's virtually impossible to tell who you're talking to when viewing the mailing lists.
Aug 31 2009
Walter Bright Wrote:http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/Have had a quick look through. You could have explained that D supports doesn't allow the same syntax too? Who knows?
Aug 31 2009
On Sun, 30 Aug 2009 17:34:36 -0400, Walter Bright <newshound1 digitalmars.com> wrote:http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/Am I missing something or did you repeat the "Let's rewrite abc and def in C to illustrate the semantics" part at the end? Is there something different I'm supposed to be reading? -Steve
Aug 31 2009
Steven Schveighoffer wrote:Am I missing something or did you repeat the "Let's rewrite abc and def in C to illustrate the semantics" part at the end? Is there something different I'm supposed to be reading?Eh, you're right.
Aug 31 2009
Sun, 30 Aug 2009 14:34:36 -0700, Walter Bright thusly wrote:http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/ This seems more like an advertisement of D than practical new information for compiler construction. Nesting functions is the basic feature of functional languages. Moreover even procedural Algol based languages such as Pascal have always supported them, too. This information is also taught in basic university level compiler courses. Now that I checked what wikipedia had to say to the matter, it also seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature <foo>' always equals 'innovation'.
Aug 31 2009
language_fan wrote:This seems more like an advertisement of D than practical new information for compiler construction. Nesting functions is the basic feature of functional languages. Moreover even procedural Algol based languages such as Pascal have always supported them, too.But not C, C++, Java, etc., so quite a lot of programmers have little experience with them, and even less understanding.This information is also taught in basic university level compiler courses.I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.Now that I checked what wikipedia had to say to the matter, it also seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature <foo>' always equals 'innovation'.Nested functions aren't innovative; they just are apparently lacking in many other popular languages, and seem to confuse a lot of people. If you google it, you'll find there's a lot of programmer confusion about them. Hence an article as to how they work is in order. In part 2, I'll cover innovative things D does with nested functions.
Aug 31 2009
Mon, 31 Aug 2009 10:37:29 -0700, Walter Bright thusly wrote:language_fan wrote:Most programmers I know don't use those languages, but then again I'm part of some minority.This seems more like an advertisement of D than practical new information for compiler construction. Nesting functions is the basic feature of functional languages. Moreover even procedural Algol based languages such as Pascal have always supported them, too.But not C, C++, Java, etc., so quite a lot of programmers have little experience with them, and even less understanding.Ok. We were taught that. We basically built a naive Pascal compiler.This information is also taught in basic university level compiler courses.I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.For what it's worth, they also seem somewhat buggy in D. Hopefully writing the articles motivates fixing those issues :) For example one can't call symbols before their declaration on non-global scope.Now that I checked what wikipedia had to say to the matter, it also seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature <foo>' always equals 'innovation'.Nested functions aren't innovative; they just are apparently lacking in many other popular languages, and seem to confuse a lot of people. If you google it, you'll find there's a lot of programmer confusion about them. Hence an article as to how they work is in order.In part 2, I'll cover innovative things D does with nested functions.Ok.
Aug 31 2009
language_fan wrote:For what it's worth, they also seem somewhat buggy in D. Hopefully writing the articles motivates fixing those issues :) For example one can't call symbols before their declaration on non-global scope.That's actually not a bug. In function scopes, you can't reference a variable before use, either.
Aug 31 2009
Walter Bright Wrote:language_fan wrote:You have to agree however that this is counter-intuitive, since functions in D can be used before they are declared, yet nested functions cant. While it follows the convention used by local variables, this isnt the same, local variables need storage, the nested functions merely need a pointer to the stack frame. Also, using delegates to dereference a nested function so it can be used as a prototype (which to me feels more like a hack than a feature) forces the entire stack frame to be allocated in _d_allocmemory. Nested functions should be parsed in the same pass as their parent method, fixing the need to use delegates which also needlessly use 8bytes in the stack frame.For what it's worth, they also seem somewhat buggy in D. Hopefully writing the articles motivates fixing those issues :) For example one can't call symbols before their declaration on non-global scope.That's actually not a bug. In function scopes, you can't reference a variable before use, either.
Aug 31 2009
I agree it would be better to allow forward references for nested functions, I just wished to point out that the current behavior is not a bug, it was built that way.
Aug 31 2009
Mon, 31 Aug 2009 13:17:11 -0700, Walter Bright thusly wrote:I agree it would be better to allow forward references for nested functions, I just wished to point out that the current behavior is not a bug, it was built that way.That's great news actually. It might even mean that this might change some day.
Sep 02 2009
language_fan wrote:I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc. -- Michiel HelvensteijnI agree it would be better to allow forward references for nested functions, I just wished to point out that the current behavior is not a bug, it was built that way.That's great news actually. It might even mean that this might change some day.
Sep 02 2009
Wed, 02 Sep 2009 13:35:05 +0200, Michiel Helvensteijn thusly wrote:language_fan wrote:While the syntax might vary a bit in functional languages, it's a common practice for the compiler to solve symbol dependencies inside the function scope. myfun:: Int -> Int -> Int myfyn a b = result b where result c = helper3 c + a helper3 = helper2 5 helper2 d c = if c == 1 then d else helper2 d (c - 1) When I first tried D, I put all my helper functions on top of all procedural code inside the function's scope, but soon noticed how badly it can fail.I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.I agree it would be better to allow forward references for nested functions, I just wished to point out that the current behavior is not a bug, it was built that way.That's great news actually. It might even mean that this might change some day.
Sep 02 2009
Michiel Helvensteijn wrote:I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; } -- Rainer Deyke - rainerd eldwood.com
Sep 02 2009
Rainer Deyke wrote:You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-) -- Michiel HelvensteijnI still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; }
Sep 02 2009
Michiel Helvensteijn wrote:Rainer Deyke wrote:I can't see how it can be done in the general case, other than by constructing a dependency tree of top-level symbols. Pass over the tree, evaluating everything which is a leaf of the tree. If you have a pass where you don't succeed in removing any leaf nodes, you have a circular dependency. DMD sort of does this, I think, but it only does two passes, and it's not very good at backing out when it discovers something is not a leaf. It'd be hard to make that efficient when there are potentially infinite passes.You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-)I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; }
Sep 02 2009
On Wed, Sep 2, 2009 at 3:29 PM, Don<nospam nospam.com> wrote:Michiel Helvensteijn wrote:It wouldn't even be that difficult. Basically if you treat forward-referenced nested functions as a sort of goto, the same rules should apply: a call to a nested function may not skip the initialization of any variables it depends on. When i's initializer is evaluated, it has not been declared yet, so the call to f is illegal. It also prevents other invalid use.Rainer Deyke wrote:I can't see how it can be done in the general case, other than by constructing a dependency tree of top-level symbols. Pass over the tree, evaluating everything which is a leaf of the tree. If you have a pass where you don't succeed in removing any leaf nodes, you have a circular dependency. DMD sort of does this, I think, but it only does two passes, and it's not very good at backing out when it discovers something is not a leaf. It'd be hard to make that efficient when there are potentially infinite passes.You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-)I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc.That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; }
Sep 02 2009
Jarrett Billingsley wrote:It wouldn't even be that difficult. Basically if you treat forward-referenced nested functions as a sort of goto, the same rules should apply: a call to a nested function may not skip the initialization of any variables it depends on. When i's initializer is evaluated, it has not been declared yet, so the call to f is illegal. It also prevents other invalid use.That's what I meant, yes. Basically, any function that reads i may not be called before i is declared, nor in i's initialization. Of course, in reality, it depends on the control flow within the function. But that's holy grail stuff. So: conservatively. -- Michiel Helvensteijn
Sep 02 2009
Michiel Helvensteijn wrote:Basically, any function that reads i may not be called before i is declared, nor in i's initialization. Of course, in reality, it depends on the control flow within the function. But that's holy grail stuff. So: conservatively.Oh, you may also not take a delegate of the function before i is declared. Same reason. -- Michiel Helvensteijn
Sep 02 2009
Walter Bright Wrote:language_fan wrote:I agree with Walter here. While D is not the first place I see closures and nested functions, it is the first language I come across that blends delegates, closures and nested functions in a simple, elegant and intuitive manner. PHP for one does not support closures at all, and delegates are done using the assign a closure to a delegate value to get a nested function. C/C++ also don't support closures, and delegates must be manually handled (function ptr + void* param) with very little support from many existing APIs (win32 is especially bad for that as it only uses static callbacks). Its no surprise that I was literally drooling when I first read about how D does it, I had just spent a few weeks doing jQuery in JavaScript for a client back then and fell in love with closures, D had it all with better syntax :) In D you can even send a function pointer to a delegate value!This seems more like an advertisement of D than practical new information for compiler construction. Nesting functions is the basic feature of functional languages. Moreover even procedural Algol based languages such as Pascal have always supported them, too.But not C, C++, Java, etc., so quite a lot of programmers have little experience with them, and even less understanding.This information is also taught in basic university level compiler courses.I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.Now that I checked what wikipedia had to say to the matter, it also seemed to mention D. Apparently 'c-like syntax' plus 'advanced feature <foo>' always equals 'innovation'.Nested functions aren't innovative; they just are apparently lacking in many other popular languages, and seem to confuse a lot of people. If you google it, you'll find there's a lot of programmer confusion about them. Hence an article as to how they work is in order. In part 2, I'll cover innovative things D does with nested functions.
Aug 31 2009
Mon, 31 Aug 2009 14:42:09 -0400, Jeremie Pelletier thusly wrote:I agree with Walter here. While D is not the first place I see closures and nested functions, it is the first language I come across that blends delegates, closures and nested functions in a simple, elegant and intuitive manner.Well..Its no surprise that I was literally drooling when I first read about how D does it, I had just spent a few weeks doing jQuery in JavaScript for a client back then and fell in love with closures, D had it all with better syntax :) In D you can even send a function pointer to a delegate value!I can see your point. I have previously mostly used OCaml, Mercury, Miranda, Haskell, SML, CL, Scheme, Qi, Ur, Clojure, Erlang, and Oz. It's not really that surprising to first find some flaws in the functional part of a new language.
Sep 02 2009
Nick Sabalausky:Quick! For each of these, valid or invalid?:I may like this one: import std.stdio: writeln; import d.templates: IsCallable; void repeat(TyCall)(int n, TyCall callme) if (IsCallable!TyCall) { foreach (i; 0 .. n) callme(i); } void main() { repeat(5, (int i){ writeln("hi"); }); } It works if callme is a delegate, function pointer or callable object, and gives good error messages otherwise. The bad thing is that currently the LDC compiler has not enough semantics to inline that delegate. If you need more performance you can use the template trick(s) used by std.algorithm of Phobos2. Bye, bearophile
Sep 02 2009
If the loop index "i" isn't necessary, you can use simpler code: import std.stdio: writeln; void repeat(TF)(int n, lazy TF callme) { foreach (i; 0 .. n) callme(); } void main() { repeat(5, writeln("hi")); } Bye, bearophile
Sep 02 2009
Nick Sabalausky wrote:"Jeremie Pelletier" <jeremiep gmail.com> wrote in message news:h7h5i1$5mp$1 digitalmars.com...While D is not the first place I see closures and nested functions, it is the first language I come across that blends delegates, closures and nested functions in a simple, elegant and intuitive manner.I almost agree. But not quite. D certainly handles much of it better than a lot of languages, and the syntax of the *actual* nested functions is nice. But there are still issues that bug the hell out of me.Quick! For each of these, valid or invalid?: // A //////////////////////// void repeat(int n, delegate void(int i) dg) { foreach(int i; 0..n) dg(i); } repeat(5, delegate void(int i) { writefln("hi"); }); // B //////////////////////// void repeat(int n, void delegate(int i) dg) { foreach(int i; 0..n) dg(i); } repeat(5, void delegate(int i) { writefln("hi"); }); // C //////////////////////// void repeat(int n, delegate void(int i) dg) { foreach(int i; 0..n) dg(i); } repeat(5, void delegate(int i) { writefln("hi"); }); // D //////////////////////// void repeat(int n, void delegate(int i) dg) { foreach(int i; 0..n) dg(i); } repeat(5, delegate void(int i) { writefln("hi"); });Also keep in mind that to increase confusion, D still supports the old style C syntax for functions. It's true that when you make a distinction between delegates, functions, nested functions and lambdas, all kinds of inconsistencies may crop up. For example the above example is much simpler in Scala (but of course scalac doesn't produce efficient native code): def foo(i: Int) = println("hi") class c { def bar(i: Int) = println("hi") } object obj extends c def scope = { def lambda = { i: Int => println("hi") } def repeat(n: Int, dg: Int => Unit) = 0.to(n-1).foreach { dg (_) } repeat(5, foo) repeat(5, obj.bar) repeat(5, (new c).bar) repeat(5, lambda) repeat(5, { i: Int => println("hi") }) } As you can see, whatever you try to do, the type system cleanly stays out of the way.
Sep 02 2009
On Wed, Sep 2, 2009 at 6:07 AM, Nick Sabalausky<a a.a> wrote:Umm, yea. If you don't already know what I'm getting at with that, then..=.Quick! For each of these, valid or invalid?:// D //////////////////////// void repeat(int n, void delegate(int i) dg) { =A0 =A0foreach(int i; 0..n) =A0 =A0 =A0 =A0dg(i); } repeat(5, delegate void(int i) { writefln("hi"); });Only valid one! I've been doing this too long ;)And now the secondary question: Which, if any, of those instances of "delegate" should be changed to "function"? (I know it's not a real serio=usproblem, but the thing is, 99.9% of the time, I don't care, and more importantly, I don't *want* to care whether or not there's a scope being passed around with the...whatever it is.)Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.
Sep 02 2009
Jarrett Billingsley wrote:Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this? Andrei
Sep 02 2009
On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 02 2009
Jarrett Billingsley wrote:On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 02 2009
Edward Diener wrote:Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs. AndreiOn Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 03 2009
Andrei Alexandrescu wrote:Edward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 03 2009
On Thu, Sep 3, 2009 at 6:48 PM, Edward Diener<eddielee_no_spam_here tropicsoft.com> wrote:What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> !There's no real reason to get rid of function pointers. What type would the .funcptr property of a delegate be, if function pointers didn't exist? You also need them for C compatibility.
Sep 03 2009
Jarrett Billingsley wrote:On Thu, Sep 3, 2009 at 6:48 PM, Edward Diener<eddielee_no_spam_here tropicsoft.com> wrote:Probably the same type as .ptr? And by the way, I find it really strange, that .funcptr results into an incorrectly typed function pointer, that basically has the wrong calling convention for the destination code, which usually is a method. It'd be different if signature of the .funcptr included an explicit argument for the hidden pointers. So that you could write: dg.funcptr(dg.ptr, arguments);What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> !There's no real reason to get rid of function pointers. What type would the .funcptr property of a delegate be, if function pointersdidn't exist? You also need them for C compatibility.And that's about the only reason to keep them. But wouldn't it be possible for the compiler to allow assignment of a function pointer to a delegate? All the compiler had to do is to generate a hidden dispatch method to "translate" the different calling conventions. The delegate's .funcptr points to that dispatch function, and the dispatch function call the actual function. If the assigned function pointer is not a statically known function (but from a variable), the function address could be stored in the delegate's .ptr. Would this work?
Sep 03 2009
On Thu, Sep 3, 2009 at 7:10 PM, grauzone<none example.net> wrote:Probably the same type as .ptr?void*? That's just silly. Let's just throw all static typing out the window. :PAnd by the way, I find it really strange, that .funcptr results into an incorrectly typed function pointer, that basically has the wrong calling convention for the destination code, which usually is a method. It'd be different if signature of the .funcptr included an explicit argument for the hidden pointers. So that you could write: dg.funcptr(dg.ptr, arguments);Yeah. There probably needs to be an extern(this) or so for functions that take a context pointer, like __thiscall in VC++. The way it works now is rather unsafe.And that's about the only reason to keep them. But wouldn't it be possible for the compiler to allow assignment of a function pointer to a delegate? All the compiler had to do is to generate a hidden dispatch method to "translate" the different calling conventions. The delegate's .funcptr points to that dispatch function, and the dispatch function call the actual function. If the assigned function pointer is not a statically known function (but from a variable), the function address could be stored in the delegate's .ptr. Would this work?Of course it'd work. And D APIs would take delegates and everyone would be happy. But it still doesn't really justify getting rid of raw function pointers.
Sep 03 2009
Edward Diener wrote:Andrei Alexandrescu wrote:Actually it could be said that C++'s exercise with pointers to member functions, which unifies a variety of functions (virtual, nonvirtual, in a host of multiple inheritance scenario), although KISS-motivated for the user, was at the same time a departure from C++'s usual approach, and a disastrous one. AndreiEdward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 03 2009
Edward Diener wrote:Andrei Alexandrescu wrote:Actually it could be said that C++'s exercise with pointers to member functions, which unifies a variety of functions (virtual, nonvirtual, in a host of multiple inheritance scenario), although KISS-motivated for the user, was at the same time a departure from C++'s usual approach, and a disastrous one. AndreiEdward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 03 2009
Andrei Alexandrescu wrote:Edward Diener wrote:Why do you think pointer to member function was a "departure from C++'s usual approach" ? Bjarne mentioned in one of his books of having considered the C++ version of a delegate as a language construct ( taking the address of an object's member function ) sometime in the design of C++ and having rejected it. I can not remember the reason but it was evidently considered. I don't think pointer to member function is a disaster, just sometimes difficult to use, and of course very limiting. I agree I would have still liked a delegate to be part of the C++ language instead of pointer to member function, since the former is much more flexible. But std::function/std::bind ( boost::function/boost::bind or boost::lambda ) solves that problem nicely at the expense of a little more syntax but with great flexibility in binding.Andrei Alexandrescu wrote:Actually it could be said that C++'s exercise with pointers to member functions, which unifies a variety of functions (virtual, nonvirtual, in a host of multiple inheritance scenario), although KISS-motivated for the user, was at the same time a departure from C++'s usual approach, and a disastrous one.Edward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 03 2009
Edward Diener wrote:Andrei Alexandrescu wrote:Don't pay for what you don't use, low-key approach to under-the-wraps magic. The pointer to member type is the most elaborate of all C++ built-in types.Edward Diener wrote:Why do you think pointer to member function was a "departure from C++'s usual approach" ?Andrei Alexandrescu wrote:Actually it could be said that C++'s exercise with pointers to member functions, which unifies a variety of functions (virtual, nonvirtual, in a host of multiple inheritance scenario), although KISS-motivated for the user, was at the same time a departure from C++'s usual approach, and a disastrous one.Edward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?Bjarne mentioned in one of his books of having considered the C++ version of a delegate as a language construct ( taking the address of an object's member function ) sometime in the design of C++ and having rejected it. I can not remember the reason but it was evidently considered.I'm not saying it was a decision made in ignorance. IMHO it was, however, a wrong decision, and experience with pointer to member functions (i.e., few even know how to write one down) supports that hypothesis.I don't think pointer to member function is a disaster, just sometimes difficult to use, and of course very limiting. I agree I would have still liked a delegate to be part of the C++ language instead of pointer to member function, since the former is much more flexible. But std::function/std::bind ( boost::function/boost::bind or boost::lambda ) solves that problem nicely at the expense of a little more syntax but with great flexibility in binding."Nice" doesn't come to my mind when thinking of the above, but the significant runtime cost does :o). Andrei
Sep 03 2009
Andrei Alexandrescu wrote:Edward Diener wrote:No kidding. When writing my "Member function pointers" CodeProject article [1], it seemed that nobody had truly documented the extent of their grotesqueness before. And during the course of writing that article, I noticed that the compiler vendor with the sanest implementation also had an alternative language called D... [1] http://www.codeproject.com/KB/cpp/FastDelegate.aspx BTW: I've just discovered that my article is referenced from the C++ FQA, with a prominent note: "WARNING: this stuff can be used to scare little children." <g>Andrei Alexandrescu wrote:Don't pay for what you don't use, low-key approach to under-the-wraps magic. The pointer to member type is the most elaborate of all C++ built-in types.Edward Diener wrote:Why do you think pointer to member function was a "departure from C++'s usual approach" ?Andrei Alexandrescu wrote:Actually it could be said that C++'s exercise with pointers to member functions, which unifies a variety of functions (virtual, nonvirtual, in a host of multiple inheritance scenario), although KISS-motivated for the user, was at the same time a departure from C++'s usual approach, and a disastrous one.Edward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?
Sep 04 2009
Andrei Alexandrescu wrote:Edward Diener wrote:If I don't use it, I don't see how I am paying for it.Andrei Alexandrescu wrote:Don't pay for what you don't use, low-key approach to under-the-wraps magic. The pointer to member type is the most elaborate of all C++ built-in types.Edward Diener wrote:Why do you think pointer to member function was a "departure from C++'s usual approach" ?Andrei Alexandrescu wrote:Actually it could be said that C++'s exercise with pointers to member functions, which unifies a variety of functions (virtual, nonvirtual, in a host of multiple inheritance scenario), although KISS-motivated for the user, was at the same time a departure from C++'s usual approach, and a disastrous one.Edward Diener wrote:Good point ! That would be fine also. The basic issue is to allow a single syntactical construct to encompass all callables in order to simplify code design. But I am still theoretically in favor of the single type, purely from KISS principles. The single delegate type subsumes the function pointer type. As far as the size savings, of course some small amount of memory can be saved. As far as the assigned speed, if the delegate type in D is as I suppose a language, and not a library, implementation, the language ( compiler ) can be smart enough to know that the programmer is assigning a function pointer to the delegate and make the speedier atomic assignment. What I imagine will happen in D is that when an updated delegate type allows itself to be initialized with a function pointer, the vast majority of D programmers will use delegate for all callables and the function pointer will remain simply an artefact of the language. Then D can eventually get rid of it <g> ! This is analogous to the transition that will happen in C++ from function pointers/member function pointers to std::function in C++0x. Of course I never expect C++ to get rid of anything because some person in 3009, going back to code 100 years old and still supported by C++30x, still uses function pointers/member function pointers and the C++ standard committee deems it impermissible to break that code <g><g> !Jarrett Billingsley wrote:IMHO it's ok if there are two types, as long as function is implicitly convertible to delegate. Function pointers have the advantage that they are only one word in size, can be assigned to atomically, and help interfacing with C callback APIs.On Wed, Sep 2, 2009 at 9:45 AM, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:I suggested this a long time back on this NG, and I am sure many others have also. A function pointer should essentially be a delegate whose object is null. That is essentially the way delegates are in .Net. In C++, boost::Function can encompass any C++ callable type so there is little theoretical reason why D should not encompass all callable types into a delegate. Having to program for any callable type, in a functional callable or signal/slots library, by dealing with the two signature variations of a function pointer and a delegate rather than a single common signature is a real PITA in an advanced programming language.Jarrett Billingsley wrote:Surprisingly, it doesn't seem like it. Walter himself, in the spec, said that "Function pointers and delegates may merge into a common syntax and be interchangeable with each other," so I just assume that no one has found it necessary to make a report. Maybe there should be.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.Did someone file a bug report on this?Hooking an object to a C++ pointer to member functions is not really rocket science syntax <g>. That they are inflexible in reusable cases, and need the scaffolding that at least boost::function/boost::bind provides to be really reuable is a given. It is easy in retrospect to say that C++ should have gone with the were many years ago in a Bell lab far away.Bjarne mentioned in one of his books of having considered the C++ version of a delegate as a language construct ( taking the address of an object's member function ) sometime in the design of C++ and having rejected it. I can not remember the reason but it was evidently considered.I'm not saying it was a decision made in ignorance. IMHO it was, however, a wrong decision, and experience with pointer to member functions (i.e., few even know how to write one down) supports that hypothesis."Nice" in the sense of: 1) Fairly easy to understand and use. 2) A lot better than what came before <g>. But that's another language and now D should unite all callables under the same delegate roof.I don't think pointer to member function is a disaster, just sometimes difficult to use, and of course very limiting. I agree I would have still liked a delegate to be part of the C++ language instead of pointer to member function, since the former is much more flexible. But std::function/std::bind ( boost::function/boost::bind or boost::lambda ) solves that problem nicely at the expense of a little more syntax but with great flexibility in binding."Nice" doesn't come to my mind when thinking of the above, but the significant runtime cost does :o).
Sep 04 2009
Jarrett Billingsley wrote:Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.The problem is that function pointers and delegates have different calling conventions. You *might* be able to rig up an asm stub that compensated for the difference... not sure. As it stands, you can just use a function to create the delegate stub for you; doesn't even require a heap allocation! http://gist.github.com/140507
Sep 02 2009
On Wed, Sep 2, 2009 at 9:49 AM, Daniel Keep<daniel.keep.lists gmail.com> wr= ote:Jarrett Billingsley wrote:Which is why I suggest that the ABI be changed ;) I suppose one method of making their calling conventions compatible would be to pass the delegate's context in what would normally be a scratch register. Delegates/member funcs would store that immediately upon entry, and normal functions wouldn't care if anything were passed.Well repeat should probably always take a delegate since most likely, you're going to be passing it a lambda. However I agree that it would be very, very nice to be able to make APIs take just delegates and allow functions to be implicitly cast to them. You can already make your own thunks, but they're not going to be as efficient as something that actually works on an ABI level.The problem is that function pointers and delegates have different calling conventions. =A0You *might* be able to rig up an asm stub that compensated for the difference... not sure.As it stands, you can just use a function to create the delegate stub for you; doesn't even require a heap allocation! http://gist.github.com/140507Wow. What a horrible mess of code to do something that should be straightforward. If this is what Andrei is thinking of when he says "introspection", well heh, I'll have no part of it. The comment about tuples not being allowed to contain out and ref is actually not entirely true. Internally type tuples are represented as parameter type tuples, which include the refness, and you can even get .stringofs that include the ref qualifiers. It instead seems that the compiler is buggy and _whether or not the refness of the params in a param tuple is preserved depends on the code using it_. Consider this gem: void foob(T: Ret function(Args), Ret, Args...)(T func) { pragma(msg, ParameterTupleOf!(T).stringof); static void wtf(ParameterTupleOf!(T) args) {} pragma(msg, ParameterTupleOf!(T).stringof); } void blah(int, ref float) {} void aojkjas() { foob(&blah); } Okay, look at foob's body. Both pragmas should print out the same thing, no= ? They don't. They print: (int, ref float) (int _param_0, float _param_1) WHAT. For one, where did the 'ref' go? For two, where did the names come from? Also, if you look at typeof(&wtf), it's also missing the ref. I'd really, really like to replace your entire module with this: Ret delegate(Args) toDg(T: Ret function(Args), Ret, Args...)(T func) { struct Wrap { T mFunc; Ret call(Args args) { return (cast(T)this)(args); } } Ret delegate(Args) dg; Wrap wrap; dg.ptr =3D func; dg.funcptr =3D &wrap.call; return dg; } But I can't. :C
Sep 02 2009
Jarrett Billingsley wrote:... void foob(T: Ret function(Args), Ret, Args...)(T func) { pragma(msg, ParameterTupleOf!(T).stringof); static void wtf(ParameterTupleOf!(T) args) {} pragma(msg, ParameterTupleOf!(T).stringof); } void blah(int, ref float) {} void aojkjas() { foob(&blah); } Okay, look at foob's body. Both pragmas should print out the same thing, no? They don't. They print: (int, ref float) (int _param_0, float _param_1) WHAT. For one, where did the 'ref' go? For two, where did the names come from? Also, if you look at typeof(&wtf), it's also missing the ref.Yeah, I've noticed this, too. Parameter tuples are just outright screwed.I'd really, really like to replace your entire module with this: Ret delegate(Args) toDg(T: Ret function(Args), Ret, Args...)(T func) { struct Wrap { T mFunc; Ret call(Args args) { return (cast(T)this)(args); } } Ret delegate(Args) dg; Wrap wrap; dg.ptr = func; dg.funcptr = &wrap.call; return dg; }You and me both. That said, this code is ported from an experimental library for binding D to lua; it used something similar to detect ref and out and change the function signature (outs became multiple returns, for example).
Sep 02 2009
Nick Sabalausky Wrote:"Jeremie Pelletier" <jeremiep gmail.com> wrote in message news:h7h5i1$5mp$1 digitalmars.com...The only valid syntax is up there, and you could use a simple closure instead of a delegate literal. As for function pointers, you can send a function pointer to a delegate value, the context only gets set to null and the method calls with a null "this", but calls nonetheless. I almost only use delegates in D, since it allows functions pointers, delegates, closures and nested functions to be passed. Function pointers only allow function pointers, but are useful for C compatibility. I almost never use delegate literals since closures can be used instead, even with a return value (works like 'auto' return values). void foo(bool delegate() dg) { dg(); } foo({return true;});While D is not the first place I see closures and nested functions, it is the first language I come across that blends delegates, closures and nested functions in a simple, elegant and intuitive manner.I almost agree. But not quite. D certainly handles much of it better than a lot of languages, and the syntax of the *actual* nested functions is nice. But there are still issues that bug the hell out of me. For instance, it's fairly common for me, in D, to write a function that takes a delegate and then call it with a delegate literal (anon func). But out of all the times I've done that, I don't think there's been a single time I haven't had to go look up the syntax. And here's why: bool delegate(int a) delegate bool(int a) Umm, yea. If you don't already know what I'm getting at with that, then... Quick! For each of these, valid or invalid?: // D //////////////////////// void repeat(int n, void delegate(int i) dg) { foreach(int i; 0..n) dg(i); } repeat(5, delegate void(int i) { writefln("hi"); }); ////////////////////////// And now the secondary question: Which, if any, of those instances of "delegate" should be changed to "function"? (I know it's not a real serious problem, but the thing is, 99.9% of the time, I don't care, and more importantly, I don't *want* to care whether or not there's a scope being passed around with the...whatever it is.) So...If you could correctly, and confidently, identify the correct answers without hesitation, especially on the first part, well...then you've got a far better mind than I do.
Sep 02 2009
On Wed, Sep 2, 2009 at 4:53 PM, Nick Sabalausky<a a.a> wrote:),void foo(bool delegate() dg) { =A0 =A0dg(); } foo({return true;});Sure, when there's no parameters (...does that work in D1, or just D2?...=but even then, I still always end up going though a process like this whe=ndefining foo:No, you can do it with params too. foo((int x) { return x; });
Sep 02 2009
Walter Bright wrote:language_fan wrote:Some universities don't even have compiler classes. Mine only covered basic parsing. Thanks for the article, Walter! :) -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenodeThis information is also taught in basic university level compiler courses.I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.
Aug 31 2009
Tom S wrote:Walter Bright wrote:Wollongong has a compiler course. They just never run it due to complete and total lack of interest in the student body. People are no fun WHATSOEVER.language_fan wrote:Some universities don't even have compiler classes. Mine only covered basic parsing. Thanks for the article, Walter! :)This information is also taught in basic university level compiler courses.I bet only a tiny fraction of programmers have taken university compiler classes. (Also, they were not covered in compiler classes I took.) Consider also that the Java JVM doesn't support static links, and last I heard the .NET IL didn't, either.
Aug 31 2009
On 2009-08-30 17:34:36 -0400, Walter Bright <newshound1 digitalmars.com> said:http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/It'strue that C doesn't have nested functions, but Apple's version of C, C++ and Objective-C, starting with Snow Leopard, has it. Well, it has nested function litterals, called blocks. And it's really nice for performing tasks in the background. The following example is an Objective-C method that adds a task to the system's global task queue, which upon completion adds a task to the application's main thread event loop to updates the user interface. - (IBAction)analyzeDocument:(NSButton *)sender { dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSDictionary *stats = [myDoc analyze]; dispatch_async(dispatch_get_main_queue(), ^{ [myModel setDict:stats]; [myStatsView setNeedsDisplay:YES]; [stats release]; }); }); } Source: Mac OS X 10.6 Snow Leopard Review, Ars Technica -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 01 2009
Michel Fortin wrote:On 2009-08-30 17:34:36 -0400, Walter Bright <newshound1 digitalmars.com> said:Oh sod blocks; the REAL awesome in that example is Grand Central Dispatch. For those who don't know, it's a parallelism framework that lets you farm off tasks to thread pools, with a few neat additions: 1) you can express dependencies and 2) the thread pools are managed by the OS itself, so it can load-balance. No doubt Microsoft will have Windows Bismuth or something for Windows 9 that's a hard to use, missed-the-point knock off. As for the FLOSS crowd, I expect that in a year or so down the track their solution will be buggy, even HARDER to use, and involve at LEAST three different and completely incompatible libraries. Plus, they have OpenCL. I've seen about a half dozen OpenCL examples specifically for non-Mac machines, but none bother to tell you how to actually GET an OpenCL implementation, or if they're even available. *sigh* I loathe Macs, but Apple seems to have hit this particular feature out of the park.http://www.reddit.com/r/programming/comments/9fk6g/how_nested_functions_work_part_1/It'strue that C doesn't have nested functions, but Apple's version of C, C++ and Objective-C, starting with Snow Leopard, has it. Well, it has nested function litterals, called blocks. ...
Sep 01 2009
On 2009-09-01 08:15:39 -0400, Daniel Keep <daniel.keep.lists gmail.com> said:Oh sod blocks; the REAL awesome in that example is Grand Central Dispatch. For those who don't know, it's a parallelism framework that lets you farm off tasks to thread pools, with a few neat additions: 1) you can express dependencies and 2) the thread pools are managed by the OS itself, so it can load-balance.And they're dead easy to use. Want an asynchronous foreach loop on the global system task queue? Here you go: dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t i) { results[i] = do_work(data, i); }); I wonder how you could do the above in D2. I mean, assuming there's a way to declare a C function taking a block argument and that you can prevent prevent the garbage collector from deallocating the heap-allocated function frame once it's given to 'dispatch_apply', "results" would need to be a shared variable (using unnecessary atomic operations?), and the heap-allocated function frame would also need to be "shared" since it's given to another thread. Can this work?Plus, they have OpenCL. I've seen about a half dozen OpenCL examples specifically for non-Mac machines, but none bother to tell you how to actually GET an OpenCL implementation, or if they're even available. *sigh*OpenCL is Apple's baby, no wonder they're a little ahead in their implementation. Just be pacient, I'm sure others will appear soon. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 01 2009
Michel Fortin Wrote:The specification is overseen by the Khronos group, Apple was a major contributor, and they had the original idea. But its not their work alone :) ATI already has a beta implemention of OpenCL, nVidia has one it releases to developers but I am too lazy to fill in the long form with just "i want to toy with it" answers. Hopefully these both reach release quality at the same time D handles 'shared' correctly :)Plus, they have OpenCL. I've seen about a half dozen OpenCL examples specifically for non-Mac machines, but none bother to tell you how to actually GET an OpenCL implementation, or if they're even available. *sigh*OpenCL is Apple's baby, no wonder they're a little ahead in their implementation. Just be pacient, I'm sure others will appear soon.
Sep 01 2009
On 2009-09-01 10:07:42 -0400, Jeremie Pelletier <jeremiep gmail.com> said:I didn't say it was their work alone. What I meant is as you said: it was there original idea. I'll leave the baby analogy out of this. -- Michel Fortin michel.fortin michelf.com http://michelf.com/OpenCL is Apple's baby, no wonder they're a little ahead in their implementation. Just be pacient, I'm sure others will appear soon.The specification is overseen by the Khronos group, Apple was a major contributor, and they had the original idea. But its not their work alone :)
Sep 01 2009
Walter Bright wrote:http://www.reddit.com/r/programming/comments/9fk6g/how_nested_fu ctions_work_part_1/Another thread on it! http://www.reddit.com/r/programming/comments/9ga7e/c_lambdas_vs_apples_c_blocks/
Sep 01 2009