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