digitalmars.D - Thin delegate adapter
- Guilherme Vieira (44/44) Jan 12 2011 Hi,
- Dmitry Olshansky (17/62) Jan 12 2011 How is it better then built-in language feature? This works just fine:
- Guilherme Vieira (15/91) Jan 12 2011 Ah, I totally missed that. But what if `s' went out of the scope and the
- Dmitry Olshansky (6/86) Jan 12 2011 That's the main point of built-in delegates - the compiler detects them
- Guilherme Vieira (8/123) Jan 12 2011 No sh*t..?! @__@ That's so cool! But is it smart enough to know the stac...
- Dmitry Olshansky (7/107) Jan 12 2011 Ehm, it can optimize certain cases but for the moment it doesn't.
- Guilherme Vieira (8/18) Jan 14 2011 Since it only uses something the size of a pointer (`b'), it might as we...
Hi, I'm wondering if a delegate adapter template like isn't handy for Phobos (it may be especially useful for std.signal): class Switch { enum State { ON, OFF } void trigger() { switch (mState) { case State.ON: mState = State.OFF; break; case State.OFF: mState = State.ON; break; default: break; } if (watch !is null) watch(mState); } void delegate(State s) watch; private State mState; } class ToggleButton { property toggled(bool toggled) { writeln("ToggleButton.toggled(", toggled, ")"); } } void main() { scope s = new Switch(); scope b = new ToggleButton(); s.watch = &b.toggled; // error: invalid conversion s.watch = adapt!("obj.toggled = cast(bool)(a)", Switch.State)(b); s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } Yes, it urges to be polished. Particularly, it doesn't support multiple arguments. I also wanted to place the argument type tuple somwhere else (actually wanted to hide it completely, but I think that's not possible). Feedback? -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira
Jan 12 2011
On 12.01.2011 15:41, Guilherme Vieira wrote:Hi, I'm wondering if a delegate adapter template like isn't handy for Phobos (it may be especially useful for std.signal): class Switch { enum State { ON, OFF } void trigger() { switch (mState) { case State.ON: mState = State..OFF; break; case State.OFF: mState = State.ON; break; default: break; } if (watch !is null) watch(mState); } void delegate(State s) watch; private State mState; } class ToggleButton { property toggled(bool toggled) { writeln("ToggleButton.toggled(", toggled, ")"); } } void main() { scope s = new Switch(); scope b = new ToggleButton(); s.watch = &b.toggled; // error: invalid conversion s.watch = adapt!("obj.toggled = cast(bool)(a)", Switch.State)(b); s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } Yes, it urges to be polished. Particularly, it doesn't support multiple arguments. I also wanted to place the argument type tuple somwhere else (actually wanted to hide it completely, but I think that's not possible). Feedback? -- Atenciosamente / Sincerely, Guilherme ("n2liquid") VieiraHow is it better then built-in language feature? This works just fine: void main() { //they can't be scope and compiler enforces this (+ scope is deprecated) //actually, the orignal code is unsafe - what hapens if adapted delegate escapes current scope? auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State a){ b.toggled = cast(bool)a; }; s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } -- Dmitry Olshansky
Jan 12 2011
Ah, I totally missed that. But what if `s' went out of the scope and the scope ended? Wouldn't the scope reference (the one containing `b') be lost and cause memory corruption? E.g.: Switch make_switch() { auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State state) { b.toggled = cast(bool)(state); }; return s; } -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky <dmitry.olsh gmail.com>wrote:On 12.01.2011 15:41, Guilherme Vieira wrote:Hi, I'm wondering if a delegate adapter template like isn't handy for Phobos (it may be especially useful for std.signal): class Switch { enum State { ON, OFF } void trigger() { switch (mState) { case State.ON: mState = State..OFF; break; case State.OFF: mState = State.ON; break; default: break; } if (watch !is null) watch(mState); } void delegate(State s) watch; private State mState; } class ToggleButton { property toggled(bool toggled) { writeln("ToggleButton.toggled(", toggled, ")"); } } void main() { scope s = new Switch(); scope b = new ToggleButton(); s.watch = &b.toggled; // error: invalid conversion s.watch = adapt!("obj.toggled = cast(bool)(a)", Switch.State)(b); s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } Yes, it urges to be polished. Particularly, it doesn't support multiple arguments. I also wanted to place the argument type tuple somwhere else (actually wanted to hide it completely, but I think that's not possible). Feedback? -- Atenciosamente / Sincerely, Guilherme ("n2liquid") VieiraHow is it better then built-in language feature? This works just fine: void main() { //they can't be scope and compiler enforces this (+ scope is deprecated) //actually, the orignal code is unsafe - what hapens if adapted delegate escapes current scope? auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State a){ b.toggled = cast(bool)a; }; s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } -- Dmitry Olshansky
Jan 12 2011
On 12.01.2011 16:07, Guilherme Vieira wrote:Ah, I totally missed that. But what if `s' went out of the scope and the scope ended? Wouldn't the scope reference (the one containing `b') be lost and cause memory corruption? E.g.: Switch make_switch() { auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State state) { b.toggled = cast(bool)(state); }; return s; }That's the main point of built-in delegates - the compiler detects them and places the enclosing stack frame on heap, so it's all sort of cool magic that just works :)-- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky <dmitry.olsh gmail.com <mailto:dmitry.olsh gmail.com>> wrote: On 12.01.2011 15:41, Guilherme Vieira wrote: Hi, I'm wondering if a delegate adapter template like isn't handy for Phobos (it may be especially useful for std.signal): class Switch { enum State { ON, OFF } void trigger() { switch (mState) { case State.ON: mState = State..OFF; break; case State.OFF: mState = State.ON; break; default: break; } if (watch !is null) watch(mState); } void delegate(State s) watch; private State mState; } class ToggleButton { property toggled(bool toggled) { writeln("ToggleButton.toggled(", toggled, ")"); } } void main() { scope s = new Switch(); scope b = new ToggleButton(); s.watch = &b.toggled; // error: invalid conversion s.watch = adapt!("obj.toggled = cast(bool)(a)", Switch.State)(b); s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } Yes, it urges to be polished. Particularly, it doesn't support multiple arguments. I also wanted to place the argument type tuple somwhere else (actually wanted to hide it completely, but I think that's not possible). Feedback? -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira How is it better then built-in language feature? This works just fine: void main() { //they can't be scope and compiler enforces this (+ scope is deprecated) //actually, the orignal code is unsafe - what hapens if adapted delegate escapes current scope? auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State a){ b.toggled = cast(bool)a; }; s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } -- Dmitry Olshansky-- Dmitry Olshansky
Jan 12 2011
No sh*t..?! __ That's so cool! But is it smart enough to know the stack frame doesn't need to go to heap in this case? (since it returns a heap object referecing another heap object, i.e. can it untangle `b' from the stack?) -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira On Wed, Jan 12, 2011 at 11:49 AM, Dmitry Olshansky <dmitry.olsh gmail.com>wrote:On 12.01.2011 16:07, Guilherme Vieira wrote:Ah, I totally missed that. But what if `s' went out of the scope and the scope ended? Wouldn't the scope reference (the one containing `b') be lost and cause memory corruption? E.g.: Switch make_switch() { auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State state) { b.toggled = cast(bool)(state); }; return s; } That's the main point of built-in delegates - the compiler detects themand places the enclosing stack frame on heap, so it's all sort of cool magic that just works :)-- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky <dmitry.olsh gmail.com<mailto: dmitry.olsh gmail.com>> wrote: On 12.01.2011 15:41, Guilherme Vieira wrote: Hi, I'm wondering if a delegate adapter template like isn't handy for Phobos (it may be especially useful for std.signal): class Switch { enum State { ON, OFF } void trigger() { switch (mState) { case State.ON: mState = State..OFF; break; case State.OFF: mState = State.ON; break; default: break; } if (watch !is null) watch(mState); } void delegate(State s) watch; private State mState; } class ToggleButton { property toggled(bool toggled) { writeln("ToggleButton.toggled(", toggled, ")"); } } void main() { scope s = new Switch(); scope b = new ToggleButton(); s.watch = &b.toggled; // error: invalid conversion s.watch = adapt!("obj.toggled = cast(bool)(a)", Switch.State)(b); s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } Yes, it urges to be polished. Particularly, it doesn't support multiple arguments. I also wanted to place the argument type tuple somwhere else (actually wanted to hide it completely, but I think that's not possible). Feedback? -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira How is it better then built-in language feature? This works just fine: void main() { //they can't be scope and compiler enforces this (+ scope is deprecated) //actually, the orignal code is unsafe - what hapens if adapted delegate escapes current scope? auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State a){ b.toggled = cast(bool)a; }; s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } -- Dmitry Olshansky-- Dmitry Olshansky
Jan 12 2011
On 13.01.2011 2:16, Guilherme Vieira wrote:No sh*t..?! __ That's so cool! But is it smart enough to know the stack frame doesn't need to go to heap in this case? (since it returns a heap object referecing another heap object, i.e. can it untangle `b' from the stack?)Ehm, it can optimize certain cases but for the moment it doesn't. Still, it needs to store b somewhere, right? and delegate is 2 pointers in fact, so b should go on heap anyway. So it narrows down to if it can save only parts of the stack frame ...-- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira On Wed, Jan 12, 2011 at 11:49 AM, Dmitry Olshansky <dmitry.olsh gmail.com <mailto:dmitry.olsh gmail.com>> wrote: On 12.01.2011 16:07, Guilherme Vieira wrote: Ah, I totally missed that. But what if `s' went out of the scope and the scope ended? Wouldn't the scope reference (the one containing `b') be lost and cause memory corruption? E.g.: Switch make_switch() { auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State state) { b.toggled = cast(bool)(state); }; return s; } That's the main point of built-in delegates - the compiler detects them and places the enclosing stack frame on heap, so it's all sort of cool magic that just works :) -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky <dmitry.olsh gmail.com <mailto:dmitry.olsh gmail.com> <mailto:dmitry.olsh gmail.com <mailto:dmitry.olsh gmail.com>>> wrote: On 12.01.2011 15:41, Guilherme Vieira wrote: Hi, I'm wondering if a delegate adapter template like isn't handy for Phobos (it may be especially useful for std.signal): class Switch { enum State { ON, OFF } void trigger() { switch (mState) { case State.ON: mState = State..OFF; break; case State.OFF: mState = State.ON; break; default: break; } if (watch !is null) watch(mState); } void delegate(State s) watch; private State mState; } class ToggleButton { property toggled(bool toggled) { writeln("ToggleButton.toggled(", toggled, ")"); } } void main() { scope s = new Switch(); scope b = new ToggleButton(); s.watch = &b.toggled; // error: invalid conversion s.watch = adapt!("obj.toggled = cast(bool)(a)", Switch.State)(b); s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } Yes, it urges to be polished. Particularly, it doesn't support multiple arguments. I also wanted to place the argument type tuple somwhere else (actually wanted to hide it completely, but I think that's not possible). Feedback? -- Atenciosamente / Sincerely, Guilherme ("n2liquid") Vieira How is it better then built-in language feature? This works just fine: void main() { //they can't be scope and compiler enforces this (+ scope is deprecated) //actually, the orignal code is unsafe - what hapens if adapted delegate escapes current scope? auto s = new Switch(); auto b = new ToggleButton(); s.watch = (Switch.State a){ b.toggled = cast(bool)a; }; s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` s.trigger(); // prints `ToggleButton.toggled(true)` s.trigger(); // prints `ToggleButton.toggled(false)` } -- Dmitry Olshansky -- Dmitry Olshansky-- Dmitry Olshansky
Jan 12 2011
On Thu, Jan 13, 2011 at 5:30 AM, Dmitry Olshansky <dmitry.olsh gmail.com>wrote:On 13.01.2011 2:16, Guilherme Vieira wrote:Since it only uses something the size of a pointer (`b'), it might as well do some trickery and use `b' as `this' and turn the delegate into (Switch.State state) { this.toggled = cast(bool)(state); } (or something of similar effect). -- Atenciosamente / Sincerely, Guilherme ("n2liquid") VieiraNo sh*t..?! __ That's so cool! But is it smart enough to know the stack frame doesn't need to go to heap in this case? (since it returns a heap object referecing another heap object, i.e. can it untangle `b' from the stack?)Ehm, it can optimize certain cases but for the moment it doesn't. Still, it needs to store b somewhere, right? and delegate is 2 pointers in fact, so b should go on heap anyway. So it narrows down to if it can save only parts of the stack frame ...
Jan 14 2011