digitalmars.D.announce - D doesn't have real closures
- Brad Anderson (3/3) Sep 11 2007 http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/
- 0ffh (64/69) Sep 11 2007 You want multicast?
- Jarrett Billingsley (32/38) Sep 11 2007 Oh please, D has variadic templates :D That, and I'd expect something l...
- Brad Anderson (4/13) Sep 11 2007 It is quoted a bit like I wrote this blog post, but I did not. I'm just
- 0ffh (3/5) Sep 12 2007 Ups, sorry, my mistake!
- Jarrett Billingsley (3/8) Sep 12 2007 Oops, misquote there. Should've been 0ffh.
- Walter Bright (5/10) Sep 11 2007 Reddit:
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (5/6) Sep 12 2007 I've posted a response on my blog:
- Walter Bright (3/13) Sep 13 2007 On reddit:
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (3/6) Sep 13 2007 Thank you for posting it. Here's the direct link:
- Russell Lewis (38/44) Sep 13 2007 I think that closures could be easily implemented using compiler-driven
- BCS (25/33) Sep 13 2007 [...]
- Russell Lewis (33/73) Sep 13 2007 I thought about these issues, but decided to not include them in the
- Guillaume B. (39/49) Sep 13 2007 I'm pretty much new to D but I've recently found std.bind.bind() and whi...
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (13/19) Sep 13 2007 Yes, first you are binding function arguments. In the inner function you...
http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/ Please digg and reddit. BA
Sep 11 2007
Brad Anderson wrote:http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/ Please digg and reddit. BAYou want multicast? Well, for multicast functions (with one parameter) it seems to be rather straightforward template programming: ---<snip>--- module multicastFunctions; template mcf(T) { class mcf { void function(T) fun; mcf next; void opCall(T x) { fun(x); if (next !is null) next(x); } mcf opCat(mcf n) { mcf m=this.dup(); m.next=n.dup(); return m; } mcf dup() { return new mcf(this); } this(mcf m) { this(m.fun,m.next); } this(void function(T) d,mcf n=null) { fun=d; next=n; } } } void fa(int x) { printf("fa(%i)\n",x); } void fb(int x) { printf("fb(%i)\n",x); } void main() { mcf!(int) a=new mcf!(int)(&fa); mcf!(int) b=new mcf!(int)(&fb); mcf!(int) c=a~b; a(1); b(2); c(3); } ---<snap>--- I am sure with all the templating wizzards floating around here someone can come up with something that is not quite as full of crap as my little proof of concept code, probably with multiple parameter feature and whatnot; dirty and obvious hack for multi parm would be to have N copies of the template for 0..N-1 parms. Regards, Frank
Sep 11 2007
"0ffh" <spam frankhirsch.net> wrote in message news:fc6mea$4d8$1 digitalmars.com...Brad Anderson wrote: I am sure with all the templating wizzards floating around here someone can come up with something that is not quite as full of crap as my little proof of concept code, probably with multiple parameter feature and whatnot; dirty and obvious hack for multi parm would be to have N copies of the template for 0..N-1 parms.Oh please, D has variadic templates :D That, and I'd expect something like this to be a value type. struct MCD(Args...) { void function(Args)[] funcs; void opCatAssign(void function(Args) f) { funcs ~= f; } void opCall(Args args) { foreach(f; funcs) f(args); } } void fa(int x) { Stdout.formatln("fa({})", x); } void fb(int x) { Stdout.formatln("fb({})", x); } void main() { MCD!(int) a; a ~= &fa; a ~= &fb; a(3); }
Sep 11 2007
Jarrett Billingsley wrote:It is quoted a bit like I wrote this blog post, but I did not. I'm just the marketing guy here. BABrad Anderson wrote: I am sure with all the templating wizzards floating around here someone can come up with something that is not quite as full of crap as my little proof of concept code, probably with multiple parameter feature and whatnot; dirty and obvious hack for multi parm would be to have N copies of the template for 0..N-1 parms.Oh please, D has variadic templates :D That, and I'd expect something like this to be a value type.
Sep 11 2007
Brad Anderson wrote:It is quoted a bit like I wrote this blog post, but I did not. I'm just the marketing guy here.Ups, sorry, my mistake! Regards, Frank
Sep 12 2007
"Brad Anderson" <brad dsource.org> wrote in message news:fc7kh6$1jin$1 digitalmars.com...Jarrett Billingsley wrote:Oops, misquote there. Should've been 0ffh.It is quoted a bit like I wrote this blog post, but I did not. I'm just the marketing guy here.Brad Anderson wrote: I am sure with all the templating wizzards floating around here
Sep 12 2007
Brad Anderson wrote:http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/ Please digg and reddit. BAReddit: http://programming.reddit.com/info/2o4we/comments Digg: http://www.digg.com/programming/D_doesn_t_have_real_closures
Sep 11 2007
Brad Anderson wrote:http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/I've posted a response on my blog: http://jcesar.totumo.net/2007/09/13/d-should-have-real-closures/ Comments? Thanks
Sep 12 2007
Julio César Carrascal Urquijo wrote:Brad Anderson wrote:On reddit: http://programming.reddit.com/newhttp://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/I've posted a response on my blog: http://jcesar.totumo.net/2007/09/13/d-should-have-real-closures/ Comments? Thanks
Sep 13 2007
Walter Bright wrote:On reddit: http://programming.reddit.com/newThank you for posting it. Here's the direct link: http://programming.reddit.com/info/2oyuz/comments
Sep 13 2007
Julio César Carrascal Urquijo wrote:Brad Anderson wrote:I think that closures could be easily implemented using compiler-driven currying. I'm thinking that we should add the syntax curry <exp> which would be valid inside delegate and function literals, and which is defined to mean: "The value of <exp> is evaluated at delegate literal creation time, and stored on the heap, then passed to the delegate literal at call time as a curried argument." Basically, the compiler would take all of the curry expressions in a literal, build a struct on the heap which contained them, then pass a pointer to that struct as a curried argument to the delegate. The thing I like about this is that it makes it obvious which arguments are passed on the heap (curry expressions) and which access stack variables (ordinary, non-curry expressions). And it's compact enough that I think it could see practical use. EXAMPLES Let's start with a simple example. You have an integer that you want to return to anybody who calls your delegate: int delegate() Foo() { int i = <whatever>; return delegate int() { return curry i; } } Now, something more complex, where you use a curry expression in the left-hand side of an assignment (and note that you can use curry expressions on function arguments): void delegate(int) BuildAssigner(int *ptr) { return delegate void(int newVal) { *(curry ptr) = newVal; }; } Something which copies values from one to another (such as binding two things together in your GUI): void delegate() BuildDelayedCopier(int *dest,int *src) { return delegate void() { *(curry dest) = *(curry src); }; } Thoughts, anyone?http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/I've posted a response on my blog: http://jcesar.totumo.net/2007/09/13/d-should-have-real-closures/
Sep 13 2007
Reply to Russell,I think that closures could be easily implemented using compiler-driven currying. I'm thinking that we should add the syntax curry <exp> which would be valid inside delegate and function literals, and which is defined to mean:[...] I like this idea. This would cover most cases where you want to have a persistent delegate. However it wouldn't cover the cases where the action is expected to modify function state. However most of the time you wont want to do that in a persistent delegate. What is more likely is that you will want to create two delegates with shared persistent state. But then you might as well generate a struct. Which, come to think of it, get back to the Idea I have always liked; delegate literals from arbitrary scope. void fn() { struct S { int i; int j; int at; }; S* s = new S // darn I want anon structs alias s this; // might this work? i = 5; j = 10; Funky(s.{at = i;}, s.{at++; return at > j;} s.{return at;}); //make three delegates that uses 's' as context ptr. }
Sep 13 2007
BCS wrote:Reply to Russell,I thought about these issues, but decided to not include them in the original post for simplicity. :) I wanted to amplify and formalize a *VERY COOL* syntax that you used in your example below, which I call "pseudo-member" syntax: DEFINITION The "pseudo-member" syntax is defined as: <structOrClassVariable>.delegate <retVal>(<args>) { <body> } to be syntax sugar for the following: delegate <retVal>(<args>) { auto this = curry <structOrClassVariable>; <modifiedBody> } where <modifiedBody> is the same as <body> except that, the expressions within are modified to use "this.<member>" as appropriate. EXAMPLE struct Foo { int a,b,c; } void delegate(int) BuildSettor(Foo *ptr) { return ptr.delegate void(int val) { a = b = c = val; } // the line above is equivalent to: return delegate void(int val) { auto this = curry val; this.a = this.b = this.c = val; } } NOTE: This syntax would *NOT* give access to private fields. Since it is simply syntax sugar for a delegate literal, it is limited to the access rights of the creator.I think that closures could be easily implemented using compiler-driven currying. I'm thinking that we should add the syntax curry <exp> which would be valid inside delegate and function literals, and which is defined to mean:[...] I like this idea. This would cover most cases where you want to have a persistent delegate. However it wouldn't cover the cases where the action is expected to modify function state. However most of the time you wont want to do that in a persistent delegate. What is more likely is that you will want to create two delegates with shared persistent state. But then you might as well generate a struct. Which, come to think of it, get back to the Idea I have always liked; delegate literals from arbitrary scope.void fn() { struct S { int i; int j; int at; }; S* s = new S // darn I want anon structs alias s this; // might this work? i = 5; j = 10; Funky(s.{at = i;}, s.{at++; return at > j;} s.{return at;}); //make three delegates that uses 's' as context ptr. }
Sep 13 2007
Julio César Carrascal Urquijo Wrote:Brad Anderson wrote:I'm pretty much new to D but I've recently found std.bind.bind() and while it's not as nice, it seems to work: ========== import std.stdio; import std.bind; class Event { private void delegate()[] m_Delegate; public void opCatAssign(void delegate() dg) { m_Delegate ~= dg; } public void fireEvent() { foreach (dg; m_Delegate) { dg(); } } } void bindEvent(T)(ref Event event, ref T source, ref T target) { void f(ref T source, ref T target) { writefln("target: %s = source: %s", target, source); } event ~= bind(&f, source, target).ptr; } void bindSomeEvent(Event event, char[] s) { auto source = "source" ~ s; auto target = s ~ "target"; bindEvent(event, source, target); } void main() { auto e = new Event(); bindSomeEvent(e, "1"); bindSomeEvent(e, "2"); bindSomeEvent(e, "3"); e.fireEvent(); } ========== Is there something wrong with this? ... Well, real closures would be much nicer, but I want to know if I'm missing something... Thanks, Guillaumehttp://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/I've posted a response on my blog: http://jcesar.totumo.net/2007/09/13/d-should-have-real-closures/ Comments? Thanks
Sep 13 2007
Guillaume B. wrote:Is there something wrong with this? ... Well, real closures would be much nicer, but I want to know if I'm missing something... Thanks, GuillaumeYes, first you are binding function arguments. In the inner function you can't use the outer function's variables without passing them as arguments and if you accidentally use one of them the compiler wont help you detect it. The second problem is that it's too cumbersome to use. The easier it is to use a feature the more uses you'll find. One of the examples in the article is ported from JavaScript where it is wildly used for it's elegance and because it works. It works in D but I don't think any D programmer will use it because it looks horrible in D. If you force a programmer to bind all variables to get something that works like a closure he'll settle with another alternative. That's the problem I see.
Sep 13 2007