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