PROPOSAL: opSeq()

Bill Baxter dnewsgroup at billbaxter.com
Tue Apr 8 16:47:20 PDT 2008


Russell Lewis wrote:
> 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


Ok.  Good examples.  Here's another that I suppose would be possible:

5) Cast-like syntaxes.  For instance the to! template in Phobos 2.x and 
Tango acts like a cast more or less, but you have to parenthesize the 
argument.    Currently:
     int x = 5;
     string y = to!(string)(x); // ok!
     string z = to!(string) x; // error!

But with your opSeq, I think the latter could be made legal, too.  IIUC.
I mention this because I keep forgetting to put those parenthesis around 
to!'s argument because it just feels so darn much like a cast.

It's an interesting idea.  Are you sure it doesn't kill 
the-ease-of-parsing requirement for the grammar?

--bb



More information about the Digitalmars-d mailing list