A possible suggestion for the Foreach loop

Kiith-Sa kiithsacmp at gmail.com
Wed Aug 21 04:34:22 PDT 2013


On Wednesday, 21 August 2013 at 10:40:10 UTC, monarch_dodra wrote:
> On Wednesday, 21 August 2013 at 02:46:06 UTC, Dylan Knutson 
> wrote:
>> Hello,
>>
>> I'd like to open up discussion regarding allowing foreach 
>> loops which iterate over a tuple of types to exist outside of 
>> function bodies. I think this would allow for templating 
>> constants and unittests easier. Take, for instance, this 
>> hypothetical example:
>>
>> ----------------------------------------------------------------------
>> T foo(T)(ref T thing)
>> {
>> 	thing++; return thing * 2;
>> }
>>
>> foreach(Type; TupleType!(int, long, uint))
>> {
>> 	unittest
>> 	{
>> 		Type tmp = 5;
>> 		assert(foo(tmp) == 12);
>> 	}
>> 	
>> 	unittest
>> 	{
>> 		Type tmp = 0;
>> 		foo(tmp);
>> 		assert(tmp == 1);
>> 	}
>> }
>> ----------------------------------------------------------------------
>>
>> Without the ability to wrap all of the unittests in a 
>> template, one would have to wrap the bodies of each unittest 
>> in an individual foreach loop. This is not only repetitive and 
>> tedious, but error prone, as changing the types tested then 
>> requires the programmer to change *every* instance of the 
>> foreach(Type; TupleType).
>>
>> A similar pattern already exists in Phobos, for testing all 
>> variants of strings (string, dstring, and wstring) and char 
>> types, as eco brought to my attention. After taking a look at 
>> some of the unittests that employ this pattern, I'm certain 
>> that code clarity and unittest quality could be improved by 
>> simply wrapping all of the individual unittests themselves in 
>> a foreach as described above.
>>
>> Now, I'm certainly no D expert, but I can't think of any 
>> breakages this change might impose on the language itself. So, 
>> I'd like to hear what the benevolent overlords and community 
>> think of the idea.
>
> This makes sense to me. After all, a static foreach no 
> different in its result from a static if. Here is an example 
> usecase:
>
> //----
> foreach(T)(TypeTuple!(float, double, real))
> {
>     void someFunction(T val)
>     {some_body;}
> }
> //----
>
> This, contrary to making someFunction a template, eagerly 
> compiles someFunction. This makes it "ship-able" in a library.
>
> Also, it avoid "over instantiations": More often than not, for 
> example, a template will be instantiated with "double", but 
> also "const double" and "immutable double".
>
> It also avoids having to over-think the template restraints.
>
> This is just one example, but I can *definitly* see it making 
> sense in over ways.
>
> ========
>
> Also, I find it strange that the above is not legal, but that 
> this works:
>
> //====
> import std.stdio, std.typecons;
>
> alias cases = TypeTuple!(2, 3, 4, 7, 8);
>
> void main()
> {
>     int i = 7;
>     switch(i)
>     {
>         //cases defined
>         foreach (v; cases)
>         {
>             case v:
>         }
>         {
>             writeln("match");
>         }
>         break;
>
>         default:
>             writeln("no match");
>     }
> }
> //====


In a previous project I needed exactly this (I needed to declare 
various class data members based on a large tuple of types.) I 
ended up having to use string mixins, which was pretty 
unreadable. So I think it is a good idea, although I have no idea 
how viable/nonintrusive is it to add this to the language.



More information about the Digitalmars-d mailing list