digitalmars.D - Thin delegate adapter
- Guilherme Vieira <n2.nitrogen gmail.com> Jan 12 2011
- Dmitry Olshansky <dmitry.olsh gmail.com> Jan 12 2011
- Dmitry Olshansky <dmitry.olsh gmail.com> Jan 12 2011
- Dmitry Olshansky <dmitry.olsh gmail.com> Jan 12 2011
- Guilherme Vieira <n2.nitrogen gmail.com> Jan 12 2011
- Guilherme Vieira <n2.nitrogen gmail.com> Jan 12 2011
- Guilherme Vieira <n2.nitrogen gmail.com> Jan 14 2011
--0016361e815cd1258c0499a58498
Content-Type: text/plain; charset=ISO-8859-1
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
--0016361e815cd1258c0499a58498
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Hi,<div><br><div>I'm wondering if a delegate adapter template like isn&=
#39;t handy for Phobos (it may be especially useful for std.signal):</div><=
div><br></div><blockquote class=3D"webkit-indent-blockquote" style=3D"margi=
n: 0 0 0 40px; border: none; padding: 0px;">
<div><div><font class=3D"Apple-style-span" face=3D"'courier new', m=
onospace">class Switch</font></div><div><font class=3D"Apple-style-span" fa=
ce=3D"'courier new', monospace">{</font></div><div><font class=3D"A=
pple-style-span" face=3D"'courier new', monospace">=A0=A0 =A0enum S=
tate { ON, OFF }</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"'co=
urier new', monospace">=A0=A0 =A0void trigger()</font></div><div><font =
class=3D"Apple-style-span" face=3D"'courier new', monospace">=A0=A0=
=A0{</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0 =A0 =A0switch (mState)</font></div><div><font class=3D"Appl=
e-style-span" face=3D"'courier new', monospace">=A0=A0 =A0 =A0 =A0{=
</font></div><div><font class=3D"Apple-style-span" face=3D"'courier new=
', monospace">=A0=A0 =A0 =A0 =A0 =A0 =A0case State.ON: mState =3D State=
.OFF; break;</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0 =A0 =A0 =A0 =A0case State.OFF: mState =3D State.ON; break;<=
/font></div><div><font class=3D"Apple-style-span" face=3D"'courier new&=
#39;, monospace">=A0=A0 =A0 =A0 =A0 =A0 =A0default: break;</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0 =A0 =A0}</font></div><div><font class=3D"Apple-style-span" =
face=3D"'courier new', monospace"><br></font></div><div><font class=
=3D"Apple-style-span" face=3D"'courier new', monospace">=A0=A0 =A0 =
=A0 =A0if (watch !is null) watch(mState);</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0}</font></div><div><font class=3D"Apple-style-span" face=3D"=
'courier new', monospace"><br></font></div><div><font class=3D"Appl=
e-style-span" face=3D"'courier new', monospace">=A0=A0 =A0void dele=
gate(State s) watch;</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"'co=
urier new', monospace">=A0=A0 =A0private State mState;</font></div><div=
<font class=3D"Apple-style-span" face=3D"'courier new', monospace"=
}</font></div>
ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"'co=
urier new', monospace">class ToggleButton</font></div><div><font class=
=3D"Apple-style-span" face=3D"'courier new', monospace">{</font></d=
iv>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0 property toggled(bool toggled)</font></div><div><font class=
=3D"Apple-style-span" face=3D"'courier new', monospace">=A0=A0 =A0{=
</font></div><div>
<font class=3D"Apple-style-span" face=3D"'courier new', monospace">=
=A0=A0 =A0 =A0 =A0writeln("ToggleButton.toggled(", toggled, "=
;)");</font></div><div><font class=3D"Apple-style-span" face=3D"'c=
ourier new', monospace">=A0=A0 =A0}</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">}</font></div><div><font class=3D"Apple-style-span" face=3D"'couri=
er new', monospace"><br></font></div><div><font class=3D"Apple-style-sp=
an" face=3D"'courier new', monospace">void main()</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">{</font></div><div><font class=3D"Apple-style-span" face=3D"'couri=
er new', monospace">=A0=A0 =A0scope s =3D new Switch();</font></div><di=
v><font class=3D"Apple-style-span" face=3D"'courier new', monospace=
">=A0=A0 =A0scope b =3D new ToggleButton();</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"'co=
urier new', monospace">=A0=A0 =A0s.watch =3D &b.toggled; // error: =
invalid conversion</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0s.watch =3D adapt!("obj.toggled =3D cast(bool)(a)"=
, Switch.State)(b);</font></div><div><font class=3D"Apple-style-span" face=
=3D"'courier new', monospace"><br>
</font></div><div><font class=3D"Apple-style-span" face=3D"'courier new=
', monospace">=A0=A0 =A0s.trigger(); // prints `</font><span class=3D"A=
pple-style-span" style=3D"font-family: 'courier new', monospace; ">=
ToggleButton.toggled(true)`</span></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0s.trigger();</font><font class=3D"Apple-style-span" face=3D"=
'courier new', monospace">=A0// prints `</font><span class=3D"Apple=
-style-span" style=3D"font-family: 'courier new', monospace; ">Togg=
leButton.toggled(false)`</span></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0s.trigger();</font><font class=3D"Apple-style-span" face=3D"=
'courier new', monospace">=A0// prints `</font><span class=3D"Apple=
-style-span" style=3D"font-family: 'courier new', monospace; ">Togg=
leButton.toggled(true)`</span></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">=A0=A0 =A0s.trigger();</font><font class=3D"Apple-style-span" face=3D"=
'courier new', monospace">=A0// prints `</font><span class=3D"Apple=
-style-span" style=3D"font-family: 'courier new', monospace; ">Togg=
leButton.toggled(false)`</span></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace">}</font></div></div></blockquote><div><br></div><div>Yes, it urges to =
be polished. Particularly, it doesn't support multiple arguments. I als=
o wanted to place the argument type tuple somwhere else (actually wanted to=
hide it completely, but I think that's not possible).</div>
<div><br></div><div>Feedback?</div><div><br>-- <br>Atenciosamente / Sincere=
ly,<br>Guilherme ("n2liquid") Vieira<br>
</div></div>
--0016361e815cd1258c0499a58498--
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") Vieira
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; }
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
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
--001485e9a89e015b850499a5e2d0
Content-Type: text/plain; charset=ISO-8859-1
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") Vieira
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
--001485e9a89e015b850499a5e2d0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Ah, I totally missed that. But what if `s' went out of the scope and th=
e scope ended? Wouldn't the scope reference (the one containing `b'=
) be lost and cause memory corruption?<div><br></div><div>E.g.:</div><div>
<br></div><blockquote class=3D"webkit-indent-blockquote" style=3D"margin: 0=
0 0 40px; border: none; padding: 0px;"><div><font class=3D"Apple-style-spa=
n" face=3D"'courier new', monospace">Switch make_switch()</font></d=
iv><div>
<font class=3D"Apple-style-span" face=3D"'courier new', monospace">=
{</font></div><div><font class=3D"Apple-style-span" face=3D"'courier ne=
w', monospace">=A0=A0 =A0auto s =3D new Switch();</font></div><div><fon=
t class=3D"Apple-style-span" face=3D"'courier new', monospace">=A0=
=A0 =A0auto b =3D new ToggleButton();</font></div>
<div><font class=3D"Apple-style-span" face=3D"'courier new', monosp=
ace"><br></font></div><span class=3D"Apple-style-span" style=3D"font-size: =
13px; border-collapse: collapse; "><font class=3D"Apple-style-span" face=3D=
"'courier new', monospace">=A0=A0 =A0s.watch =3D (Switch.State stat=
e) { b.toggled =3D cast(bool)(</font></span><span class=3D"Apple-style-span=
" style=3D"font-family: 'courier new', monospace; font-size: 13px; =
border-collapse: collapse; ">state</span><span class=3D"Apple-style-span" s=
tyle=3D"font-family: 'courier new', monospace; font-size: 13px; bor=
der-collapse: collapse; ">); };</span></blockquote>
<blockquote class=3D"webkit-indent-blockquote" style=3D"margin: 0 0 0 40px;=
border: none; padding: 0px;"><span class=3D"Apple-style-span" style=3D"fon=
t-size: 13px; border-collapse: collapse; "><font class=3D"Apple-style-span"=
face=3D"'courier new', monospace"><br>
</font></span><div><font class=3D"Apple-style-span" face=3D"'courier ne=
w', monospace">=A0=A0 =A0return s;</font></div><div><font class=3D"Appl=
e-style-span" face=3D"'courier new', monospace">}</font></div></blo=
ckquote><div>
<div><br></div><div>--=A0<br>Atenciosamente / Sincerely,<br>Guilherme (&quo=
t;n2liquid") Vieira<br><div><br><div class=3D"gmail_quote">On Wed, Jan=
12, 2011 at 10:57 AM, Dmitry Olshansky <span dir=3D"ltr"><<a href=3D"ma=
ilto:dmitry.olsh gmail.com">dmitry.olsh gmail.com</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex;"><div><div></div><div class=3D"h5">On 12.01.=
2011 15:41, Guilherme Vieira wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Hi,<br>
<br>
I'm wondering if a delegate adapter template like isn't handy for P=
hobos (it may be especially useful for std.signal):<br>
<br>
=A0 =A0class Switch<br>
=A0 =A0{<br>
=A0 =A0 =A0 =A0enum State { ON, OFF }<br>
<br>
=A0 =A0 =A0 =A0void trigger()<br>
=A0 =A0 =A0 =A0{<br>
=A0 =A0 =A0 =A0 =A0 =A0switch (mState)<br>
=A0 =A0 =A0 =A0 =A0 =A0{<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case State.ON: mState =3D State..OFF; break=
;<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case State.OFF: mState =3D State.ON; break;=
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0default: break;<br>
=A0 =A0 =A0 =A0 =A0 =A0}<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0if (watch !is null) watch(mState);<br>
=A0 =A0 =A0 =A0}<br>
<br>
=A0 =A0 =A0 =A0void delegate(State s) watch;<br>
<br>
=A0 =A0 =A0 =A0private State mState;<br>
=A0 =A0}<br>
<br>
=A0 =A0class ToggleButton<br>
=A0 =A0{<br>
=A0 =A0 =A0 =A0 property toggled(bool toggled)<br>
=A0 =A0 =A0 =A0{<br>
=A0 =A0 =A0 =A0 =A0 =A0writeln("ToggleButton.toggled(", toggled,=
")");<br>
=A0 =A0 =A0 =A0}<br>
=A0 =A0}<br>
<br>
=A0 =A0void main()<br>
=A0 =A0{<br>
=A0 =A0 =A0 =A0scope s =3D new Switch();<br>
=A0 =A0 =A0 =A0scope b =3D new ToggleButton();<br>
<br>
=A0 =A0 =A0 =A0s.watch =3D &b.toggled; // error: invalid conversion<br=
;, Switch.State)(b);<br>
<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(true)`<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(false)`<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(true)`<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(false)`<br>
=A0 =A0}<br>
<br>
<br>
Yes, it urges to be polished. Particularly, it doesn't support multiple=
arguments. I also wanted to place the argument type tuple somwhere else (a=
ctually wanted to hide it completely, but I think that's not possible).=
<br>
<br>
Feedback?<br>
<br>
-- <br>
Atenciosamente / Sincerely,<br>
Guilherme ("n2liquid") Vieira<br>
</blockquote></div></div>
How is it better then built-in language feature? This works just fine:<br>
=A0 =A0void main()<br>
=A0 =A0{<br>
//they can't be scope =A0and compiler enforces this (+ scope is depreca=
ted)<br>
//actually, the orignal code is unsafe - what hapens if adapted delegate es=
capes current scope?<br>
=A0 =A0 =A0 =A0auto s =3D new Switch();<br>
=A0 =A0 =A0 =A0auto b =3D new ToggleButton();<br>
<br>
<br>
=A0 =A0 =A0 =A0s.watch =3D (Switch.State a){ b.toggled =3D cast(bool)a; };=
<div class=3D"im"><br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(true)`<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(false)`<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(true)`<br>
=A0 =A0 =A0 =A0s.trigger(); // prints `ToggleButton.toggled(false)`<br>
=A0 =A0}<br>
<br></div>
-- <br><font color=3D"#888888">
Dmitry Olshansky<br><br></font></blockquote></div>
</div></div></div>
--001485e9a89e015b850499a5e2d0--
Jan 12 2011
--00163628430a7d94930499ae6326
Content-Type: text/plain; charset=ISO-8859-1
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 them
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
--00163628430a7d94930499ae6326
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
No sh*t..?! __ =A0That's so cool! But is it smart enough to know the s=
tack 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' f=
rom the stack?)<div>
<div><br></div><div>--=A0<br>Atenciosamente / Sincerely,<br>Guilherme (&quo=
t;n2liquid") Vieira</div><div><br><br><div class=3D"gmail_quote">On We=
d, Jan 12, 2011 at 11:49 AM, Dmitry Olshansky <span dir=3D"ltr"><<a href=
=3D"mailto:dmitry.olsh gmail.com">dmitry.olsh gmail.com</a>></span> wrot=
e:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex;"><div class=3D"im">On 12.01.2011 16:07, Guil=
herme Vieira wrote:<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div class=3D"im">
Ah, I totally missed that. But what if `s' went out of the scope and th=
e scope ended? Wouldn't the scope reference (the one containing `b'=
) be lost and cause memory corruption?<br>
<br>
E.g.:<br>
<br>
=A0 =A0Switch make_switch()<br>
=A0 =A0{<br></div><div class=3D"im">
=A0 =A0 =A0 =A0auto s =3D new Switch();<br>
=A0 =A0 =A0 =A0auto b =3D new ToggleButton();<br>
<br></div><div class=3D"im">
=A0 =A0 =A0 =A0s.watch =3D (Switch.State state) { b.toggled =3D cast(bool)=
(state); };<br>
<br>
<br>
=A0 =A0 =A0 =A0return s;<br>
=A0 =A0}<br>
<br>
<br>
</div></blockquote>
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 :)<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im">
-- <br>
Atenciosamente / Sincerely,<br>
Guilherme ("n2liquid") Vieira<br>
<br></div><div><div></div><div class=3D"h5">
On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky <<a href=3D"mailto:dm=
itry.olsh gmail.com" target=3D"_blank">dmitry.olsh gmail.com</a> <mailto=
:<a href=3D"mailto:dmitry.olsh gmail.com" target=3D"_blank">dmitry.olsh gma=
il.com</a>>> wrote:<br>
<br>
=A0 =A0On 12.01.2011 15:41, Guilherme Vieira wrote:<br>
<br>
=A0 =A0 =A0 =A0Hi,<br>
<br>
=A0 =A0 =A0 =A0I'm wondering if a delegate adapter template like isn&#=
39;t handy<br>
=A0 =A0 =A0 =A0for Phobos (it may be especially useful for std.signal):<br=
=A0 =A0 =A0 =A0 =A0 class Switch<br>
=A0 =A0 =A0 =A0 =A0 {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 enum State { ON, OFF }<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 void trigger()<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 switch (mState)<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case State.ON: mState =3D Stat=
e..OFF; break;<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case State.OFF: mState =3D Sta=
te.ON; break;<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 default: break;<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (watch !is null) watch(mState);<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 }<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 void delegate(State s) watch;<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 private State mState;<br>
=A0 =A0 =A0 =A0 =A0 }<br>
<br>
=A0 =A0 =A0 =A0 =A0 class ToggleButton<br>
=A0 =A0 =A0 =A0 =A0 {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 property toggled(bool toggled)<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 writeln("ToggleButton.toggled(&qu=
ot;, toggled, ")");<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 }<br>
=A0 =A0 =A0 =A0 =A0 }<br>
<br>
=A0 =A0 =A0 =A0 =A0 void main()<br>
=A0 =A0 =A0 =A0 =A0 {<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 scope s =3D new Switch();<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 scope b =3D new ToggleButton();<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 s.watch =3D &b.toggled; // error: invalid =
conversion<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 s.watch =3D adapt!("obj.toggled =3D cast(=
bool)(a)",<br>
=A0 =A0 =A0 =A0Switch.State)(b);<br>
<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 s.trigger(); // prints `ToggleButton.toggled(t=
rue)`<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 s.trigger(); // prints `ToggleButton.toggled(f=
alse)`<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 s.trigger(); // prints `ToggleButton.toggled(t=
rue)`<br>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 s.trigger(); // prints `ToggleButton.toggled(f=
alse)`<br>
=A0 =A0 =A0 =A0 =A0 }<br>
<br>
<br>
=A0 =A0 =A0 =A0Yes, it urges to be polished. Particularly, it doesn't =
support<br>
=A0 =A0 =A0 =A0multiple arguments. I also wanted to place the argument typ=
e<br>
=A0 =A0 =A0 =A0tuple somwhere else (actually wanted to hide it completely,=
<br>
=A0 =A0 =A0 =A0but I think that's not possible).<br>
<br>
=A0 =A0 =A0 =A0Feedback?<br>
<br>
=A0 =A0 =A0 =A0-- =A0 =A0 =A0 =A0 Atenciosamente / Sincerely,<br>
=A0 =A0 =A0 =A0Guilherme ("n2liquid") Vieira<br>
<br>
=A0 =A0How is it better then built-in language feature? This works just fi=
ne:<br>
=A0 =A0 =A0 void main()<br>
=A0 =A0 =A0 {<br>
=A0 =A0//they can't be scope =A0and compiler enforces this (+ scope is=
<br>
=A0 =A0deprecated)<br>
=A0 =A0//actually, the orignal code is unsafe - what hapens if adapted<br>
=A0 =A0delegate escapes current scope?<br>
=A0 =A0 =A0 =A0 =A0 auto s =3D new Switch();<br>
=A0 =A0 =A0 =A0 =A0 auto b =3D new ToggleButton();<br>
<br>
<br>
=A0 =A0 =A0 =A0 =A0 s.watch =3D (Switch.State a){ b.toggled =3D cast(bool)=
a; };<br>
<br>
=A0 =A0 =A0 =A0 =A0 s.trigger(); // prints `ToggleButton.toggled(true)`<br=
r>
=A0 =A0 =A0 =A0 =A0 s.trigger(); // prints `ToggleButton.toggled(true)`<br=
r>
=A0 =A0 =A0 }<br>
<br>
=A0 =A0-- =A0 =A0 Dmitry Olshansky<br>
<br>
</div></div></blockquote>
<br>
<br>
-- <br><font color=3D"#888888">
Dmitry Olshansky<br><br></font></blockquote></div>
</div></div>
--00163628430a7d94930499ae6326--
Jan 12 2011
--0016362846188e05010499cdfe36 Content-Type: text/plain; charset=ISO-8859-1 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: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 ...
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") Vieira --0016362846188e05010499cdfe36 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Thu, Jan 13, 2011 at 5:30 AM, Dmitry Olshansk= y <span dir=3D"ltr"><<a href=3D"mailto:dmitry.olsh gmail.com">dmitry.ols= h gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" styl= e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div class=3D"im">On 13.01.2011 2:16, Guilherme Vieira wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> No sh*t..?! __ That's so cool! But is it smart enough to know the sta= ck frame doesn't need to go to heap in this case? (since it returns a h= eap object referecing another heap object, i.e. can it untangle `b' fro= m the stack?)<br> </blockquote> <br></div> Ehm, it can optimize certain cases but for the moment it doesn't.<br> 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 o= nly parts of the stack frame ...<br></blockquote></div><br>Since it only us= es something the size of a pointer (`b'), it might as well do some tric= kery and use `b' as `this' and turn the delegate into <span style= =3D"font-family: courier new,monospace;">(Switch.State state) { this.toggle= d =3D cast(bool)(state); }</span> (or something of similar effect).<br clea= r=3D"all"> <br>-- <br>Atenciosamente / Sincerely,<br>Guilherme ("n2liquid") = Vieira<br> --0016362846188e05010499cdfe36--
Jan 14 2011









Dmitry Olshansky <dmitry.olsh gmail.com> 