PROPOSAL: opSeq()

Russell Lewis webmaster at villagersonline.com
Tue Apr 8 06:56:07 PDT 2008


Bill Baxter wrote:
> Russell Lewis wrote:
>> PROPOSAL: A way to handle sequences of expressions which otherwise 
>> would have been syntax errors
>>
>>
>> EXAMPLE CODE:
>>     my_for(i=0, i<10, i++) { <code> }
> 
> Are you familiar with the "trailing delegates" proposal?
> 
> Basically the idea there is that any {<code>} block following a function 
> call would be treated as an extra argument to the function.
> 
> So if you write the function:
> void my_for(lazy void init, lazy bool test, lazy void inc, void delegate())
> { ... }
> 
> then your EXAMPLE_CODE above would call that function.

Yes, I am familiar with the concept.  My proposal is a generalization of 
that which is able to handle any type of expression, and also to handle 
multiple expressions.

OPEN QUESTION: What happens if an opSeq-type struct is *not* followed by 
anything?  Do we need syntax to indicate whether that is legal or not?

You asked how opSeq is better than trailing delegates, so here are some 
more examples of things that opSeq can do:



1) Bare statements.  Take a look at my implementation of the MyFor 
struct from the original post.  One of the overloads of opSeq takes 
"lazy void block", which means that this syntax is also legal:
	my_for(i=0, i<10, i++)
		a = a+1;

2) Suffixes.  People have suggested that the expression
	3 + 2i
be something that can be implemented entirely as a library.  If i was a 
variable and we supported "opSeqRev", then it would be easy!

3) Multiple arguments.  Trailing delegates can't implement complex 
syntaxes, such as do...while.  opSeq can.  At the bottom of this post, 
I'll post code that will handle all of the following:
	MyWhile(a != b) <bare statement>;
	MyWhile(a != b) { <block>}
	MyDo <bare statement> MyWhile(a != b);
	MyDo { <block> } MyWhile(a != b);

4) Generalized syntax.  The examples above indicate to me that a lot of 
D's syntax could be implemented in a library using opSeq.  Would that 
allow many of D's constructs to be first class entities?  Might that 
allow us to implement more functional-language type features?



Here's the example code I promised:

BEGIN CODE

struct While
{
   bool delegate() cond;

   void opSeq(lazy void bareStatement)
   {
     opSeq({ bareStatement(); });
   }
   void opSeq(void delegate() block)
   {
     if(cond())
     {
BEGIN_LOOP:  // so I don't have to use D's while!
       block();
       if(cond())
         goto BEGIN_LOOP;
     }
   }
}

While MyWhile(lazy bool cond)
{
   While ret;
     ret.cond = cond;
   return ret;
}


struct Do
{
   void opSeq(lazy void bareStatement, While the_while)
   {
     opSeq({ bareStatement(); }, the_while);
   }
   void opSeq(void delegate() block, While the_while)
   {
     block();
     the_while block;
   }
}

// this isn't a function, it's a variable.  that's because
// the use of MyDo doesn't use parens.
Do MyDo;

END CODE



More information about the Digitalmars-d mailing list