shortcut for dynamic dispatch and operators

Steven Schveighoffer schveiguy at yahoo.com
Tue Dec 1 10:01:30 PST 2009


On Tue, 01 Dec 2009 12:27:07 -0500, Bill Baxter <wbaxter at gmail.com> wrote:

> On Tue, Dec 1, 2009 at 8:58 AM, Steven Schveighoffer
> <schveiguy at yahoo.com> wrote:
>> On Tue, 01 Dec 2009 11:24:17 -0500, Bill Baxter <wbaxter at gmail.com>  
>> wrote:
>>
>>> On Tue, Dec 1, 2009 at 6:30 AM, Steven Schveighoffer
>>> <schveiguy at yahoo.com> wrote:
>>>>
>>>> An idea I just had when thinking about how ugly opDispatch and  
>>>> opBinary
>>>> operators will be if we get those was, wouldn't it be cool if the
>>>> compiler
>>>> could translate:
>>>>
>>>> myTemplateMethod("abc" || "def")() if(condition) {}
>>>>
>>>> to
>>>>
>>>> myTemplateMethod(string __x)() if((__x == "abc" || __x == "def") &&
>>>> condition) {}
>>>>
>>>> It makes dispatch based on compile-time strings much more palatable,  
>>>> for
>>>> example:
>>>>
>>>> opDispatch("foo" || "bar")() {...}
>>>> opBinary("+" || "-" || "*")(int rhs) {...}
>>>>
>>>> instead of:
>>>>
>>>> opDispatch(string fn)() if(fn == "foo" || fn == "bar") {...}
>>>> opBinary(string op)() if(op == "+" || op == "-" || op == "*")(int rhs)
>>>> {...}
>>>>
>>>> In fact, it can be generalized to any type which has literals:
>>>>
>>>> factorial(int x)(){ return factorial!(x-1)() * x;}
>>>> factorial(1)() { return 1;}
>>>>
>>>> What I don't know is if the || works in all cases -- because something
>>>> like
>>>> true || false is a valid expression.  Maybe someone can come up with a
>>>> better way.
>>>
>>> The closest thing is the specialization syntax:
>>>
>>>    factorial(int x : 1)() { return 1;}
>>>
>>> The main problem with your suggestion is that for most practical uses
>>> you actually need to know what the parameter was, not just that it was
>>> either "foo" or "bar".
>>
>> Yeah, I thought the __x in my example would have to be some pre-defined
>> symbol, but I realized that if you had multiple such parameters it  
>> wouldn't
>> work...
>>
>>> So you need to put a symbol somewhere in that
>>> signature to bind the actual value to.
>>>
>>> But I agree, some syntax like
>>>   opDispatch(x : "foo" || "bar")() {  /* use x */ ...}
>>
>> I like that, that works for me.  I'd even like:
>>
>> opDispatch(string x : "foo" || "bar")() {}
>>
>> better than having to do the if clause at the end of the signature.
>>
>>>
>>> would look much nicer.  And it's pretty close to current
>>> specialization syntax for values.  The type "string" can be
>>> auto-deduced from the stuff after the colon.  But there are more
>>> conditions that you'd like to test than just "||".  I guess I'd prefer
>>> to just be able to move a whole if clause to after a colon.
>>>
>>>    void opDispatch(fn : fn == "foo" || fn == "bar")(Variant arg...) {}
>>
>> You can do the full if clause with the current syntax if you need more
>> complex situations than just matching against a list.  I wasn't looking  
>> to
>> replace the template contracts, I just think the most common case for
>> opDispatch and opBinary is going to be "if symbol is this or that or the
>> other thing", so it should be easier to use than the template contracts.
>>  With your syntax, it's almost an extension of current syntax, so it  
>> might
>> be doable (type inference would be a nice bonus).
>
> Well with "x in array" syntax you could do
>
>    void opDispatch(fn : fn in ["foo","bar"])(Variant arg...) {}

That would also work for me.  But I prefer not having to repeat the  
template parameter name.  My goal is to have templated operators as  
straightforward to type out as it is today:

opAdd(int rhs)

=>

opBinary(op: "+")(int rhs)

This looks like the closest so far that is consistent with current syntax.

> Part of what annoys me about the if clauses is just that they are
> separated from the template arguments by the function arguments (or by
> other template arguments), so I'd like to see a way to put those
> conditions closer to the parameters they're constraining, regardless
> of the brevity aspect.  In fact something like this would be nice:
>
> void aTemplate(
>        fn  if(fn in ["foo","bar"]),
>        Args... if (Args.length == 2))
> (Args x)
> {
>        ...
> }

Yes, that can be annoying, but you still need the global 'if' in case you  
want to constrain on multiple arguments.  However, it seems like a  
reasonable optimization to allow placing if statements after a template  
parameter.  It definitely would make for better readability when the if  
clauses are complex, but it's still a little more clunky than I would like  
for implementing an individual operator.

-Steve



More information about the Digitalmars-d mailing list