www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A const idiom + a different 'delete'

reply bearophile <bearophileHUGS lycos.com> writes:
This is an little idiom that is getting common in my code, it's similar to the
'transients' of Clojure language.

Often I have to build a simple data structure like an array associative or
another kind of array, it needs to be mutable because I fill it in few lines of
code code. When it's complete I never need to change it again, so now I'd like
it to be const. I can't freeze it, so I have to create a new variable:


void main() {
    int[int] aa_;
    foreach (i; 0 .. 10)
        aa_[i] = i * i;

    // now I'd like to freeze aa
    const(int[int]) aa = aa_;
}


If the array is fixed-sized the situation is worse because the last line copies
the whole array.

Sometimes I use a small function to do this.

This is an alternative way to write it that I've never used because I don't
like it much:

void main() {
    const(int[int]) aa = {
        int[int] result;
        foreach (i; 0 .. 10)
            result[i] = i * i;
        return result;
    }();
}


In Python I sometimes use "delete" to remove a name from the local namespace
that I don't want to use any more. This cleaning purpose may be a replacement
purpose for the delete keyword, but I don't know if you like it:


void main() {
    int[int] aa_;
    foreach (i; 0 .. 10)
        aa_[i] = i * i;

    // now I'd like to freeze aa
    const(int[int]) aa = aa_;
    delete aa_; // from now on the 'aa_' name can't be seen/used.
}


Here delete doesn't clean the aa_, it just removes the aa_ name from the local
namespace. If there's another reference to aa_ it is unchanged and it sees an
unchanged associative array. The point of removing the aa_ name is to keep the
namespace tidy.

As with variable definitions a goto can't jump over one delete. In Python you
can later create a new variable with the same name, but in D the variable
doesn't actually vanish from the stack, so I think it's better to disallow
successive redefinitions of it.

Bye,
bearophile
Aug 11 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
 Here delete doesn't clean the aa_, it just removes the aa_ name from the local
namespace.

It's similar to the #undef directive of C. Bye, bearophile
Aug 11 2010
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016e64eaefce5e89d048d8f61a9
Content-Type: text/plain; charset=ISO-8859-1

Actually that was a pretty useless example. const needs to be evaluable at
compile-time, so why did I bother creating a template function? lol..

On Wed, Aug 11, 2010 at 7:03 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 I think a more appropriate word for that would be "hide", or maybe
 "freeze".

 Here's another alternative, if you can call it that :p :

 import std.stdio;

 auto freeze(alias dg)()
 {
     return cast(const) dg();
 }

 void main() {
     auto aa = freeze!(

     {
         int[int] aa_;
         foreach (i; 0 .. 10)
             aa_[i] = i * i;

         return aa_;
     });

     writeln(aa, " ", typeid(aa));
 }

 But that returns const(const(int)[int]).

 I'm not sure if there's a way to hide a symbol, appart from introducing
 another scope with { }. That wouldn't work in this case, since you want a
 const type back. Perhaps using the "variant" type from Phobos could do the
 trick.. I haven't played with that yet.


 On Wed, Aug 11, 2010 at 6:01 PM, bearophile <bearophileHUGS lycos.com>wrote:

 Here delete doesn't clean the aa_, it just removes the aa_ name from the

It's similar to the #undef directive of C. Bye, bearophile


--0016e64eaefce5e89d048d8f61a9 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Actually that was a pretty useless example. const needs to be evaluable at = compile-time, so why did I bother creating a template function? lol..<br><b= r><div class=3D"gmail_quote">On Wed, Aug 11, 2010 at 7:03 PM, Andrej Mitrov= ic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andr= ej.mitrovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">I think a more ap= propriate word for that would be &quot;hide&quot;, or maybe &quot;freeze&qu= ot;.<br> <br>Here&#39;s another alternative, if you can call it that :p :<br><br>imp= ort std.stdio;<br><br>auto freeze(alias dg)()<br> {<br>=A0=A0=A0 return cast(const) dg();<br>}<br><br>void main() {<br>=A0=A0= =A0 auto aa =3D freeze!(<div class=3D"im"><br>=A0=A0=A0 {<br>=A0=A0=A0=A0= =A0=A0=A0 int[int] aa_;<br>=A0=A0=A0=A0=A0=A0=A0 foreach (i; 0 .. 10)<br>= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 aa_[i] =3D i * i;<br><br></div>=A0=A0=A0= =A0=A0=A0=A0 return aa_;<br> =A0=A0=A0 });<br> =A0=A0=A0 <br>=A0=A0=A0 writeln(aa, &quot; &quot;, typeid(aa));<br>}<br><br=
But that returns const(const(int)[int]).<br><br>I&#39;m not sure if there&=

}. That wouldn&#39;t work in this case, since you want a const type back. P= erhaps using the &quot;variant&quot; type from Phobos could do the trick.. = I haven&#39;t played with that yet.<div> <div></div><div class=3D"h5"><br> <br><div class=3D"gmail_quote">On Wed, Aug 11, 2010 at 6:01 PM, bearophile = <span dir=3D"ltr">&lt;<a href=3D"mailto:bearophileHUGS lycos.com" target=3D= "_blank">bearophileHUGS lycos.com</a>&gt;</span> wrote:<br><blockquote clas= s=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px soli= d rgb(204, 204, 204); padding-left: 1ex;"> <div>&gt; Here delete doesn&#39;t clean the aa_, it just removes the aa_ na= me from the local namespace.<br> <br> </div>It&#39;s similar to the #undef directive of C.<br> <br> Bye,<br> <font color=3D"#888888">bearophile<br> </font></blockquote></div><br> </div></div></blockquote></div><br> --0016e64eaefce5e89d048d8f61a9--
Aug 11 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--001636417fa34e132a048d8f3b81
Content-Type: text/plain; charset=ISO-8859-1

I think a more appropriate word for that would be "hide", or maybe "freeze".

Here's another alternative, if you can call it that :p :

import std.stdio;

auto freeze(alias dg)()
{
    return cast(const) dg();
}

void main() {
    auto aa = freeze!(
    {
        int[int] aa_;
        foreach (i; 0 .. 10)
            aa_[i] = i * i;

        return aa_;
    });

    writeln(aa, " ", typeid(aa));
}

But that returns const(const(int)[int]).

I'm not sure if there's a way to hide a symbol, appart from introducing
another scope with { }. That wouldn't work in this case, since you want a
const type back. Perhaps using the "variant" type from Phobos could do the
trick.. I haven't played with that yet.

On Wed, Aug 11, 2010 at 6:01 PM, bearophile <bearophileHUGS lycos.com>wrote:

 Here delete doesn't clean the aa_, it just removes the aa_ name from the

It's similar to the #undef directive of C. Bye, bearophile

--001636417fa34e132a048d8f3b81 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable I think a more appropriate word for that would be &quot;hide&quot;, or mayb= e &quot;freeze&quot;.<br><br>Here&#39;s another alternative, if you can cal= l it that :p :<br><br>import std.stdio;<br><br>auto freeze(alias dg)()<br> {<br>=A0=A0=A0 return cast(const) dg();<br>}<br><br>void main() {<br>=A0=A0= =A0 auto aa =3D freeze!(<br>=A0=A0=A0 {<br>=A0=A0=A0=A0=A0=A0=A0 int[int] a= a_;<br>=A0=A0=A0=A0=A0=A0=A0 foreach (i; 0 .. 10)<br>=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 aa_[i] =3D i * i;<br><br>=A0=A0=A0=A0=A0=A0=A0 return aa_;<br>= =A0=A0=A0 });<br> =A0=A0=A0 <br>=A0=A0=A0 writeln(aa, &quot; &quot;, typeid(aa));<br>}<br><br=
But that returns const(const(int)[int]).<br><br>I&#39;m not sure if there&=

}. That wouldn&#39;t work in this case, since you want a const type back. P= erhaps using the &quot;variant&quot; type from Phobos could do the trick.. = I haven&#39;t played with that yet.<br> <br><div class=3D"gmail_quote">On Wed, Aug 11, 2010 at 6:01 PM, bearophile = <span dir=3D"ltr">&lt;<a href=3D"mailto:bearophileHUGS lycos.com">bearophil= eHUGS lycos.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" = style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 20= 4); padding-left: 1ex;"> <div class=3D"im">&gt; Here delete doesn&#39;t clean the aa_, it just remov= es the aa_ name from the local namespace.<br> <br> </div>It&#39;s similar to the #undef directive of C.<br> <br> Bye,<br> <font color=3D"#888888">bearophile<br> </font></blockquote></div><br> --001636417fa34e132a048d8f3b81--
Aug 11 2010
prev sibling next sibling parent reply Jonathan M Davis <jmdavisprog gmail.com> writes:
On Wednesday, August 11, 2010 08:59:29 bearophile wrote:
 This is an little idiom that is getting common in my code, it's similar to
 the 'transients' of Clojure language.
 
 Often I have to build a simple data structure like an array associative or
 another kind of array, it needs to be mutable because I fill it in few
 lines of code code. When it's complete I never need to change it again, so
 now I'd like it to be const. I can't freeze it, so I have to create a new
 variable:
 
 
 void main() {
     int[int] aa_;
     foreach (i; 0 .. 10)
         aa_[i] = i * i;
 
     // now I'd like to freeze aa
     const(int[int]) aa = aa_;
 }
 
 
 If the array is fixed-sized the situation is worse because the last line
 copies the whole array.
 
 Sometimes I use a small function to do this.
 
 This is an alternative way to write it that I've never used because I don't
 like it much:
 
 void main() {
     const(int[int]) aa = {
         int[int] result;
         foreach (i; 0 .. 10)
             result[i] = i * i;
         return result;
     }();
 }
 
 
 In Python I sometimes use "delete" to remove a name from the local
 namespace that I don't want to use any more. This cleaning purpose may be
 a replacement purpose for the delete keyword, but I don't know if you like
 it:
 
 
 void main() {
     int[int] aa_;
     foreach (i; 0 .. 10)
         aa_[i] = i * i;
 
     // now I'd like to freeze aa
     const(int[int]) aa = aa_;
     delete aa_; // from now on the 'aa_' name can't be seen/used.
 }
 
 
 Here delete doesn't clean the aa_, it just removes the aa_ name from the
 local namespace. If there's another reference to aa_ it is unchanged and
 it sees an unchanged associative array. The point of removing the aa_ name
 is to keep the namespace tidy.
 
 As with variable definitions a goto can't jump over one delete. In Python
 you can later create a new variable with the same name, but in D the
 variable doesn't actually vanish from the stack, so I think it's better to
 disallow successive redefinitions of it.
 
 Bye,
 bearophile

I think that's a total no-go because it would depend on program flow. You're trying to alter a compile-time property at runtime. All it takes is having delete within an if statement, and all of a sudden, depending on how your program runs, the name may or may not be visible. You kind hide the variable creation inside another scope if you want this sort of behavior: void main() { const(int[int]) aa; { int[int] aa_; foreach(i; 0 .. 10) aa_[i] = i * i; aa = aa_; } } That naturally removes the name from the namespace just fine. It's possible that this particular idiom calls for some sort of language addition or having something added to Phobos, but removing symbols from a namespace with statements is not going to work very well - if at all - in a compiled, statically-typed language like D. - Jonathan M Davis
Aug 11 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:
 I think that's a total no-go because it would depend on program flow.

You are of course right, it's the silly thing of the day. The #undef works because it's not scoped.
You kind hide the variable creation inside another scope if you want this sort
of behavior:<

You can't do that, you can't modify a const variable in that way :-) I will just keep two variables, one immutable and one mutable, as in the first example. Later, bearophile
Aug 11 2010
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:
 I think that's a total no-go because it would depend on program flow. You're 
 trying to alter a compile-time property at runtime. All it takes is having 
 delete within an if statement, and all of a sudden, depending on how your 
 program runs, the name may or may not be visible.

I don't agree. To test a runtime value you need an if statement, and it creates the scope of its then and else parts, if you remove a variable inside one of those two scopes, x is present again when the then and else scopes are finished. So what's the problem? import std.conv: to; void main(string[] args) { int x = 10; enum int y = 5; // here x can be used if (args.length > 1) { // here x can be used delete x; // here x can't be used float x; // not allowed } else { // here x can be used } // here x can be used static if (y < 2) delete x; // here x can or can't be used according to the compile-time value of y } Bye, bearophile
Aug 11 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--e0cb4e88782721fe1c048d8f9448
Content-Type: text/plain; charset=ISO-8859-1

The scope trick won't work. You can't modify a const after the declaration.

On Wed, Aug 11, 2010 at 7:26 PM, Jonathan M Davis <jmdavisprog gmail.com>wrote:

 On Wednesday, August 11, 2010 08:59:29 bearophile wrote:
 This is an little idiom that is getting common in my code, it's similar

 the 'transients' of Clojure language.

 Often I have to build a simple data structure like an array associative

 another kind of array, it needs to be mutable because I fill it in few
 lines of code code. When it's complete I never need to change it again,

 now I'd like it to be const. I can't freeze it, so I have to create a new
 variable:


 void main() {
     int[int] aa_;
     foreach (i; 0 .. 10)
         aa_[i] = i * i;

     // now I'd like to freeze aa
     const(int[int]) aa = aa_;
 }


 If the array is fixed-sized the situation is worse because the last line
 copies the whole array.

 Sometimes I use a small function to do this.

 This is an alternative way to write it that I've never used because I

 like it much:

 void main() {
     const(int[int]) aa = {
         int[int] result;
         foreach (i; 0 .. 10)
             result[i] = i * i;
         return result;
     }();
 }


 In Python I sometimes use "delete" to remove a name from the local
 namespace that I don't want to use any more. This cleaning purpose may be
 a replacement purpose for the delete keyword, but I don't know if you

 it:


 void main() {
     int[int] aa_;
     foreach (i; 0 .. 10)
         aa_[i] = i * i;

     // now I'd like to freeze aa
     const(int[int]) aa = aa_;
     delete aa_; // from now on the 'aa_' name can't be seen/used.
 }


 Here delete doesn't clean the aa_, it just removes the aa_ name from the
 local namespace. If there's another reference to aa_ it is unchanged and
 it sees an unchanged associative array. The point of removing the aa_

 is to keep the namespace tidy.

 As with variable definitions a goto can't jump over one delete. In Python
 you can later create a new variable with the same name, but in D the
 variable doesn't actually vanish from the stack, so I think it's better

 disallow successive redefinitions of it.

 Bye,
 bearophile

I think that's a total no-go because it would depend on program flow. You're trying to alter a compile-time property at runtime. All it takes is having delete within an if statement, and all of a sudden, depending on how your program runs, the name may or may not be visible. You kind hide the variable creation inside another scope if you want this sort of behavior: void main() { const(int[int]) aa; { int[int] aa_; foreach(i; 0 .. 10) aa_[i] = i * i; aa = aa_; } } That naturally removes the name from the namespace just fine. It's possible that this particular idiom calls for some sort of language addition or having something added to Phobos, but removing symbols from a namespace with statements is not going to work very well - if at all - in a compiled, statically-typed language like D. - Jonathan M Davis

--e0cb4e88782721fe1c048d8f9448 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable The scope trick won&#39;t work. You can&#39;t modify a const after the decl= aration.<br><br><div class=3D"gmail_quote">On Wed, Aug 11, 2010 at 7:26 PM,= Jonathan M Davis <span dir=3D"ltr">&lt;<a href=3D"mailto:jmdavisprog gmail= .com">jmdavisprog gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><div></div><= div class=3D"h5">On Wednesday, August 11, 2010 08:59:29 bearophile wrote:<b= r> &gt; This is an little idiom that is getting common in my code, it&#39;s si= milar to<br> &gt; the &#39;transients&#39; of Clojure language.<br> &gt;<br> &gt; Often I have to build a simple data structure like an array associativ= e or<br> &gt; another kind of array, it needs to be mutable because I fill it in few= <br> &gt; lines of code code. When it&#39;s complete I never need to change it a= gain, so<br> &gt; now I&#39;d like it to be const. I can&#39;t freeze it, so I have to c= reate a new<br> &gt; variable:<br> &gt;<br> &gt;<br> &gt; void main() {<br> &gt; =A0 =A0 int[int] aa_;<br> &gt; =A0 =A0 foreach (i; 0 .. 10)<br> &gt; =A0 =A0 =A0 =A0 aa_[i] =3D i * i;<br> &gt;<br> &gt; =A0 =A0 // now I&#39;d like to freeze aa<br> &gt; =A0 =A0 const(int[int]) aa =3D aa_;<br> &gt; }<br> &gt;<br> &gt;<br> &gt; If the array is fixed-sized the situation is worse because the last li= ne<br> &gt; copies the whole array.<br> &gt;<br> &gt; Sometimes I use a small function to do this.<br> &gt;<br> &gt; This is an alternative way to write it that I&#39;ve never used becaus= e I don&#39;t<br> &gt; like it much:<br> &gt;<br> &gt; void main() {<br> &gt; =A0 =A0 const(int[int]) aa =3D {<br> &gt; =A0 =A0 =A0 =A0 int[int] result;<br> &gt; =A0 =A0 =A0 =A0 foreach (i; 0 .. 10)<br> &gt; =A0 =A0 =A0 =A0 =A0 =A0 result[i] =3D i * i;<br> &gt; =A0 =A0 =A0 =A0 return result;<br> &gt; =A0 =A0 }();<br> &gt; }<br> &gt;<br> &gt;<br> &gt; In Python I sometimes use &quot;delete&quot; to remove a name from the= local<br> &gt; namespace that I don&#39;t want to use any more. This cleaning purpose= may be<br> &gt; a replacement purpose for the delete keyword, but I don&#39;t know if = you like<br> &gt; it:<br> &gt;<br> &gt;<br> &gt; void main() {<br> &gt; =A0 =A0 int[int] aa_;<br> &gt; =A0 =A0 foreach (i; 0 .. 10)<br> &gt; =A0 =A0 =A0 =A0 aa_[i] =3D i * i;<br> &gt;<br> &gt; =A0 =A0 // now I&#39;d like to freeze aa<br> &gt; =A0 =A0 const(int[int]) aa =3D aa_;<br> &gt; =A0 =A0 delete aa_; // from now on the &#39;aa_&#39; name can&#39;t be= seen/used.<br> &gt; }<br> &gt;<br> &gt;<br> &gt; Here delete doesn&#39;t clean the aa_, it just removes the aa_ name fr= om the<br> &gt; local namespace. If there&#39;s another reference to aa_ it is unchang= ed and<br> &gt; it sees an unchanged associative array. The point of removing the aa_ = name<br> &gt; is to keep the namespace tidy.<br> &gt;<br> &gt; As with variable definitions a goto can&#39;t jump over one delete. In= Python<br> &gt; you can later create a new variable with the same name, but in D the<b= r> &gt; variable doesn&#39;t actually vanish from the stack, so I think it&#39= ;s better to<br> &gt; disallow successive redefinitions of it.<br> &gt;<br> &gt; Bye,<br> &gt; bearophile<br> <br> </div></div>I think that&#39;s a total no-go because it would depend on pro= gram flow. You&#39;re<br> trying to alter a compile-time property at runtime. All it takes is having<= br> delete within an if statement, and all of a sudden, depending on how your<b= r> program runs, the name may or may not be visible. You kind hide the variabl= e<br> creation inside another scope if you want this sort of behavior:<br> <div class=3D"im"><br> void main()<br> {<br> =A0 =A0const(int[int]) aa;<br> <br> =A0 =A0{<br> </div><div class=3D"im"> =A0 =A0 =A0 =A0int[int] aa_;<br> =A0 =A0 =A0 =A0foreach(i; 0 .. 10)<br> =A0 =A0 =A0 =A0 =A0 =A0aa_[i] =3D i * i;<br> </div> =A0 =A0 =A0 =A0aa =3D aa_;<br> =A0 =A0}<br> }<br> <br> <br> That naturally removes the name from the namespace just fine. It&#39;s poss= ible that<br> this particular idiom calls for some sort of language addition or having<br=

ments<br> is not going to work very well - if at all - in a compiled, statically-type= d<br> language like D.<br> <font color=3D"#888888"><br> - Jonathan M Davis<br> </font></blockquote></div><br> --e0cb4e88782721fe1c048d8f9448--
Aug 11 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016364ed220a01456048d8f967f
Content-Type: text/plain; charset=ISO-8859-1

p.s. Sorry about quoting large ammounts of text, I need to break out of that
habbit.

On Wed, Aug 11, 2010 at 7:28 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 The scope trick won't work. You can't modify a const after the declaration.

--0016364ed220a01456048d8f967f Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable p.s. Sorry about quoting large ammounts of text, I need to break out of tha= t habbit.<br><br><div class=3D"gmail_quote">On Wed, Aug 11, 2010 at 7:28 PM= , Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich = gmail.com">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">The scope trick w= on&#39;t work. You can&#39;t modify a const after the declaration.</blockqu= ote> </div><br> --0016364ed220a01456048d8f967f--
Aug 11 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisprog gmail.com> writes:
On Wednesday, August 11, 2010 10:52:30 bearophile wrote:
 Jonathan M Davis:
 I think that's a total no-go because it would depend on program flow.

You are of course right, it's the silly thing of the day. The #undef works because it's not scoped.
You kind hide the variable creation inside another scope if you want this
sort of behavior:<

You can't do that, you can't modify a const variable in that way :-) I will just keep two variables, one immutable and one mutable, as in the first example. Later, bearophile

Hits self on head. It's the whole issue with not being able to break out the referent from the reference declaring it const. Bleh. I wish that we'd found a better solution to that. In any case, then you should be able to use Rebindable to fix the problem. The other possibility is to just create a function to return the variable. That way, the const variable gets properly initialized rather than having to find a way to assign to it later. - Jonathan M Davis
Aug 11 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
Here's how I'd do it:

void main() {
    const T[] buildArray() {
          T[] t;
          // fill in t

           return t;
    }

   const T[] t = buildArray;
}

So the creation is factored away into that nested function which is
used to initialized the reference that you keep around.
Aug 11 2010
prev sibling parent reply Shin Fujishiro <rsinfu gmail.com> writes:
bearophile <bearophileHUGS lycos.com> wrote:
 This is an alternative way to write it that I've never used because I don't
like it much:
 
 void main() {
     const(int[int]) aa = {
         int[int] result;
         foreach (i; 0 .. 10)
             result[i] = i * i;
         return result;
     }();
 }

It looks like LISP's (let ...) expression and personally I like it. The idiom is really useful for building immutable things, including compile-time constants. And recently I found it works well with string mixins. -------------------- import std.conv; auto ref reverseArgs(alias fun, Args...)(auto ref Args args) { return mixin( { string rargs; foreach (i, Arg; Args) { if (i > 0) rargs ~= ", "; rargs ~= "args[" ~ to!string(args.length - i - 1) ~ "]"; } return "fun(" ~ rargs ~ ")"; }()); } void main() { int div(int a, int b) { return a / b; } assert(reverseArgs!div(3, 27) == 9); }
Aug 12 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Shin Fujishiro:
 import std.conv;
 
 auto ref reverseArgs(alias fun, Args...)(auto ref Args args)
 {
     return mixin(
         {
             string rargs;
             foreach (i, Arg; Args)
             {
                 if (i > 0)
                     rargs ~= ", ";
                 rargs ~= "args[" ~ to!string(args.length - i - 1) ~ "]";
             }
             return "fun(" ~ rargs ~ ")";
         }());
 }
 
 void main()
 {
     int div(int a, int b) { return a / b; }
 
     assert(reverseArgs!div(3, 27) == 9);
 }

I think this is more readable (not tested much): import std.typecons: TypeTuple; // this needs to be template of std.typecons template ReverseTypeTuple(T...) { // too much long name static if (T.length) alias TypeTuple!(ReverseTypeTuple!(T[1 .. $]), T[0]) ReverseTypeTuple; else alias T ReverseTypeTuple; } auto ref reverseArgs(alias fun, Args...)(auto ref Args args) { return fun(ReverseTypeTuple!args); } int div(int a, int b) { return a / b; } void main() { assert(reverseArgs!div(3, 27) == 9); } Bye, bearophile
Aug 12 2010