www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Thin delegate adapter

reply Guilherme Vieira <n2.nitrogen gmail.com> writes:
--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&#39;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"&#39;courier new&#39;, m=
onospace">class Switch</font></div><div><font class=3D"Apple-style-span" fa=
ce=3D"&#39;courier new&#39;, monospace">{</font></div><div><font class=3D"A=
pple-style-span" face=3D"&#39;courier new&#39;, monospace">=A0=A0 =A0enum S=
tate { ON, OFF }</font></div>
<div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp=
ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"&#39;co=
urier new&#39;, monospace">=A0=A0 =A0void trigger()</font></div><div><font =
class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">=A0=A0=
 =A0{</font></div>
<div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp=
ace">=A0=A0 =A0 =A0 =A0switch (mState)</font></div><div><font class=3D"Appl=
e-style-span" face=3D"&#39;courier new&#39;, monospace">=A0=A0 =A0 =A0 =A0{=
</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;courier new=
&#39;, 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"&#39;courier new&#39;, 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"&#39;courier new&=
#39;, monospace">=A0=A0 =A0 =A0 =A0 =A0 =A0default: break;</font></div>
<div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp=
ace">=A0=A0 =A0 =A0 =A0}</font></div><div><font class=3D"Apple-style-span" =
face=3D"&#39;courier new&#39;, monospace"><br></font></div><div><font class=
=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">=A0=A0 =A0 =
=A0 =A0if (watch !is null) watch(mState);</font></div>
<div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp=
ace">=A0=A0 =A0}</font></div><div><font class=3D"Apple-style-span" face=3D"=
&#39;courier new&#39;, monospace"><br></font></div><div><font class=3D"Appl=
e-style-span" face=3D"&#39;courier new&#39;, monospace">=A0=A0 =A0void dele=
gate(State s) watch;</font></div>
<div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp=
ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"&#39;co=
urier new&#39;, monospace">=A0=A0 =A0private State mState;</font></div><div=
<font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace"=
}</font></div>

ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"&#39;co= urier new&#39;, monospace">class ToggleButton</font></div><div><font class= =3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">{</font></d= iv> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">=A0=A0 =A0 property toggled(bool toggled)</font></div><div><font class= =3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">=A0=A0 =A0{= </font></div><div> <font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">= =A0=A0 =A0 =A0 =A0writeln(&quot;ToggleButton.toggled(&quot;, toggled, &quot= ;)&quot;);</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;c= ourier new&#39;, monospace">=A0=A0 =A0}</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">}</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;couri= er new&#39;, monospace"><br></font></div><div><font class=3D"Apple-style-sp= an" face=3D"&#39;courier new&#39;, monospace">void main()</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">{</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;couri= er new&#39;, monospace">=A0=A0 =A0scope s =3D new Switch();</font></div><di= v><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace= ">=A0=A0 =A0scope b =3D new ToggleButton();</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace"><br></font></div><div><font class=3D"Apple-style-span" face=3D"&#39;co= urier new&#39;, monospace">=A0=A0 =A0s.watch =3D &amp;b.toggled; // error: = invalid conversion</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">=A0=A0 =A0s.watch =3D adapt!(&quot;obj.toggled =3D cast(bool)(a)&quot;= , Switch.State)(b);</font></div><div><font class=3D"Apple-style-span" face= =3D"&#39;courier new&#39;, monospace"><br> </font></div><div><font class=3D"Apple-style-span" face=3D"&#39;courier new= &#39;, monospace">=A0=A0 =A0s.trigger(); // prints `</font><span class=3D"A= pple-style-span" style=3D"font-family: &#39;courier new&#39;, monospace; ">= ToggleButton.toggled(true)`</span></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">=A0=A0 =A0s.trigger();</font><font class=3D"Apple-style-span" face=3D"= &#39;courier new&#39;, monospace">=A0// prints `</font><span class=3D"Apple= -style-span" style=3D"font-family: &#39;courier new&#39;, monospace; ">Togg= leButton.toggled(false)`</span></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">=A0=A0 =A0s.trigger();</font><font class=3D"Apple-style-span" face=3D"= &#39;courier new&#39;, monospace">=A0// prints `</font><span class=3D"Apple= -style-span" style=3D"font-family: &#39;courier new&#39;, monospace; ">Togg= leButton.toggled(true)`</span></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">=A0=A0 =A0s.trigger();</font><font class=3D"Apple-style-span" face=3D"= &#39;courier new&#39;, monospace">=A0// prints `</font><span class=3D"Apple= -style-span" style=3D"font-family: &#39;courier new&#39;, monospace; ">Togg= leButton.toggled(false)`</span></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monosp= ace">}</font></div></div></blockquote><div><br></div><div>Yes, it urges to = be polished. Particularly, it doesn&#39;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&#39;s not possible).</div> <div><br></div><div>Feedback?</div><div><br>-- <br>Atenciosamente / Sincere= ly,<br>Guilherme (&quot;n2liquid&quot;) Vieira<br> </div></div> --0016361e815cd1258c0499a58498--
Jan 12 2011
next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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
prev sibling next sibling parent Guilherme Vieira <n2.nitrogen gmail.com> writes:
--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&#39; went out of the scope and th= e scope ended? Wouldn&#39;t the scope reference (the one containing `b&#39;= ) 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"&#39;courier new&#39;, monospace">Switch make_switch()</font></d= iv><div> <font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">= {</font></div><div><font class=3D"Apple-style-span" face=3D"&#39;courier ne= w&#39;, monospace">=A0=A0 =A0auto s =3D new Switch();</font></div><div><fon= t class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, monospace">=A0= =A0 =A0auto b =3D new ToggleButton();</font></div> <div><font class=3D"Apple-style-span" face=3D"&#39;courier new&#39;, 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= "&#39;courier new&#39;, 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: &#39;courier new&#39;, monospace; font-size: 13px; = border-collapse: collapse; ">state</span><span class=3D"Apple-style-span" s= tyle=3D"font-family: &#39;courier new&#39;, 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"&#39;courier new&#39;, monospace"><br> </font></span><div><font class=3D"Apple-style-span" face=3D"&#39;courier ne= w&#39;, monospace">=A0=A0 =A0return s;</font></div><div><font class=3D"Appl= e-style-span" face=3D"&#39;courier new&#39;, monospace">}</font></div></blo= ckquote><div> <div><br></div><div>--=A0<br>Atenciosamente / Sincerely,<br>Guilherme (&quo= t;n2liquid&quot;) Vieira<br><div><br><div class=3D"gmail_quote">On Wed, Jan= 12, 2011 at 10:57 AM, Dmitry Olshansky <span dir=3D"ltr">&lt;<a href=3D"ma= ilto:dmitry.olsh gmail.com">dmitry.olsh gmail.com</a>&gt;</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&#39;m wondering if a delegate adapter template like isn&#39;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(&quot;ToggleButton.toggled(&quot;, toggled,= &quot;)&quot;);<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 &amp;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&#39;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&#39;s not possible).= <br> <br> Feedback?<br> <br> -- <br> Atenciosamente / Sincerely,<br> Guilherme (&quot;n2liquid&quot;) 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&#39;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
prev sibling next sibling parent Guilherme Vieira <n2.nitrogen gmail.com> writes:
--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&#39;s so cool! But is it smart enough to know the s= tack frame doesn&#39;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&#39; f= rom the stack?)<div> <div><br></div><div>--=A0<br>Atenciosamente / Sincerely,<br>Guilherme (&quo= t;n2liquid&quot;) 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">&lt;<a href= =3D"mailto:dmitry.olsh gmail.com">dmitry.olsh gmail.com</a>&gt;</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&#39; went out of the scope and th= e scope ended? Wouldn&#39;t the scope reference (the one containing `b&#39;= ) 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&#39;s the main point of built-in delegates - the compiler detects them= and places the enclosing stack frame on heap, so it&#39;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 (&quot;n2liquid&quot;) Vieira<br> <br></div><div><div></div><div class=3D"h5"> On Wed, Jan 12, 2011 at 10:57 AM, Dmitry Olshansky &lt;<a href=3D"mailto:dm= itry.olsh gmail.com" target=3D"_blank">dmitry.olsh gmail.com</a> &lt;mailto= :<a href=3D"mailto:dmitry.olsh gmail.com" target=3D"_blank">dmitry.olsh gma= il.com</a>&gt;&gt; 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&#39;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(&quot;ToggleButton.toggled(&qu= ot;, toggled, &quot;)&quot;);<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 &amp;b.toggled; // error: invalid = conversion<br> =A0 =A0 =A0 =A0 =A0 =A0 =A0 s.watch =3D adapt!(&quot;obj.toggled =3D cast(= bool)(a)&quot;,<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&#39;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&#39;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 (&quot;n2liquid&quot;) 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&#39;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
prev sibling parent Guilherme Vieira <n2.nitrogen gmail.com> writes:
--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">&lt;<a href=3D"mailto:dmitry.olsh gmail.com">dmitry.ols= h gmail.com</a>&gt;</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&#39;s so cool! But is it smart enough to know the sta= ck frame doesn&#39;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&#39; fro= m the stack?)<br> </blockquote> <br></div> Ehm, it can optimize certain cases but for the moment it doesn&#39;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&#39;), it might as well do some tric= kery and use `b&#39; as `this&#39; 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 (&quot;n2liquid&quot;) = Vieira<br> --0016362846188e05010499cdfe36--
Jan 14 2011