digitalmars.D - shortcut for dynamic dispatch and operators
- Steven Schveighoffer (22/22) Dec 01 2009 An idea I just had when thinking about how ugly opDispatch and opBinary ...
- KennyTM~ (5/27) Dec 01 2009 Alternative suggestion:
- Andrei Alexandrescu (6/48) Dec 01 2009 It's a bit difficult to see a very thin operator mask a linear
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (3/53) Dec 01 2009 What do you suggest using when you need to find out if an object is in
- Bill Baxter (6/14) Dec 01 2009 ,
- Bill Baxter (6/18) Dec 01 2009 o it
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (5/20) Dec 01 2009 I find
- Michel Fortin (14/26) Dec 01 2009 I don't like making this compile-time only. There are many cases where
- Bill Baxter (22/42) Dec 01 2009 r
- Steven Schveighoffer (15/65) Dec 01 2009 Yeah, I thought the __x in my example would have to be some pre-defined ...
- Bill Baxter (26/97) Dec 01 2009 :
- Steven Schveighoffer (15/116) Dec 01 2009 That would also work for me. But I prefer not having to repeat the
- bearophile (4/5) Dec 01 2009 That's something more useful than the sum of usefulness of opDispatch, o...
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (7/14) Dec 01 2009 I somewhat agree. For small arrays I find it very useful, I use it all
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. -Steve
Dec 01 2009
On Dec 1, 09 22:30, Steven Schveighoffer 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. -SteveAlternative suggestion: Make "x in y" returns a bool and works for arrays. Then you can write int opBinary(string s)(int rhs) if (s in ["+", "-", "*", "/", "^", "|", "&"]) { ... }
Dec 01 2009
KennyTM~ wrote:On Dec 1, 09 22:30, Steven Schveighoffer wrote:It's a bit difficult to see a very thin operator mask a linear operation, but I'm thinking maybe "x in y" could be defined if y is a compile-time array. In that case, the compiler knows the operation and the operand so it may decide to change representation as it finds fit. AndreiAn 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. -SteveAlternative suggestion: Make "x in y" returns a bool and works for arrays. Then you can write int opBinary(string s)(int rhs) if (s in ["+", "-", "*", "/", "^", "|", "&"]) { ... }
Dec 01 2009
Andrei Alexandrescu wrote:KennyTM~ wrote:What do you suggest using when you need to find out if an object is in an array? Arrays lacking opIn bothers me.On Dec 1, 09 22:30, Steven Schveighoffer wrote:It's a bit difficult to see a very thin operator mask a linear operation, but I'm thinking maybe "x in y" could be defined if y is a compile-time array. In that case, the compiler knows the operation and the operand so it may decide to change representation as it finds fit. AndreiAn 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. -SteveAlternative suggestion: Make "x in y" returns a bool and works for arrays. Then you can write int opBinary(string s)(int rhs) if (s in ["+", "-", "*", "/", "^", "|", "&"]) { ... }
Dec 01 2009
On Tue, Dec 1, 2009 at 12:15 PM, Pelle M=E5nsson <pelle.mansson gmail.com> = wrote:,It's a bit difficult to see a very thin operator mask a linear operation=itbut I'm thinking maybe "x in y" could be defined if y is a compile-time array. In that case, the compiler knows the operation and the operand so=I'm guessing Andrei would recommend std.range.find. --bbmay decide to change representation as it finds fit. AndreiWhat do you suggest using when you need to find out if an object is in an array? Arrays lacking opIn bothers me.
Dec 01 2009
On Tue, Dec 1, 2009 at 12:23 PM, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Dec 1, 2009 at 12:15 PM, Pelle M=E5nsson <pelle.mansson gmail.com= wrote:n,It's a bit difficult to see a very thin operator mask a linear operatio=o itbut I'm thinking maybe "x in y" could be defined if y is a compile-time array. In that case, the compiler knows the operation and the operand s=nmay decide to change representation as it finds fit. AndreiWhat do you suggest using when you need to find out if an object is in a=er... std.algorithm.find, I mean. --bbarray? Arrays lacking opIn bothers me.I'm guessing Andrei would recommend std.range.find.
Dec 01 2009
Bill Baxter wrote:On Tue, Dec 1, 2009 at 12:23 PM, Bill Baxter <wbaxter gmail.com> wrote:I find if (x in [1, 2, 3]) { } more clear than if ([1, 2, 3].find(x).length != 0) { }On Tue, Dec 1, 2009 at 12:15 PM, Pelle M�nsson <pelle.mansson gmail.com> wrote:er... std.algorithm.find, I mean. --bbI'm guessing Andrei would recommend std.range.find.It's a bit difficult to see a very thin operator mask a linear operation, but I'm thinking maybe "x in y" could be defined if y is a compile-time array. In that case, the compiler knows the operation and the operand so it may decide to change representation as it finds fit. AndreiWhat do you suggest using when you need to find out if an object is in an array? Arrays lacking opIn bothers me.
Dec 01 2009
On 2009-12-01 14:01:26 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:KennyTM~ wrote:I don't like making this compile-time only. There are many cases where you may want to do the same check at runtime and it'd be a bother to need a different syntax. Better to create a wrapper struct for such arrays: s in set("+", "-", "*", "/", "^", "|", "&") where set() returns a Set!string struct wrapping a sorted array of those operators for which 'in' could work fast even at runtime. Make sure it works with CTFE and you have what you want. -- Michel Fortin michel.fortin michelf.com http://michelf.com/Alternative suggestion: Make "x in y" returns a bool and works for arrays. Then you can write int opBinary(string s)(int rhs) if (s in ["+", "-", "*", "/", "^", "|", "&"]) { ... }It's a bit difficult to see a very thin operator mask a linear operation, but I'm thinking maybe "x in y" could be defined if y is a compile-time array. In that case, the compiler knows the operation and the operand so it may decide to change representation as it finds fit.
Dec 01 2009
On Tue, Dec 1, 2009 at 6:30 AM, Steven Schveighoffer <schveiguy 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 compile=rcould translate: myTemplateMethod("abc" || "def")() if(condition) {} to myTemplateMethod(string __x)() if((__x =3D=3D "abc" || __x =3D=3D "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 =3D=3D "foo" || fn =3D=3D "bar") {...} opBinary(string op)() if(op =3D=3D "+" || op =3D=3D "-" || op =3D=3D "*")=(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 li=ketrue || false is a valid expression. =A0Maybe 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". 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 */ ...} 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 =3D=3D "foo" || fn =3D=3D "bar")(Variant arg...= ) {} --bb
Dec 01 2009
On Tue, 01 Dec 2009 11:24:17 -0500, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Dec 1, 2009 at 6:30 AM, Steven Schveighoffer <schveiguy yahoo.com> wrote: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...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".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). -Steve
Dec 01 2009
On Tue, Dec 1, 2009 at 8:58 AM, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Tue, 01 Dec 2009 11:24:17 -0500, Bill Baxter <wbaxter gmail.com> wrote=:) &&On Tue, Dec 1, 2009 at 6:30 AM, Steven Schveighoffer <schveiguy 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 =3D=3D "abc" || __x =3D=3D "def"=rcondition) {} It makes dispatch based on compile-time strings much more palatable, fo=")(int rhs)example: opDispatch("foo" || "bar")() {...} opBinary("+" || "-" || "*")(int rhs) {...} instead of: opDispatch(string fn)() if(fn =3D=3D "foo" || fn =3D=3D "bar") {...} opBinary(string op)() if(op =3D=3D "+" || op =3D=3D "-" || op =3D=3D "*=a{...} 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. =A0Maybe someone can come up with ='tYeah, 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=better way.The closest thing is the specialization syntax: =A0 =A0factorial(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".work...arg...) {}So you need to put a symbol somewhere in that signature to bind the actual value to. But I agree, some syntax like =A0 opDispatch(x : "foo" || "bar")() { =A0/* use x */ ...}I like that, that works for me. =A0I'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. =A0And it's pretty close to current specialization syntax for values. =A0The type "string" can be auto-deduced from the stuff after the colon. =A0But there are more conditions that you'd like to test than just "||". =A0I guess I'd prefer to just be able to move a whole if clause to after a colon. =A0 =A0void opDispatch(fn : fn =3D=3D "foo" || fn =3D=3D "bar")(Variant =You can do the full if clause with the current syntax if you need more complex situations than just matching against a list. =A0I wasn't looking=toreplace 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. =A0With your syntax, it's almost an extension of current syntax, so it mi=ghtbe 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...) {} 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 =3D=3D 2)) (Args x) { ... } --bb
Dec 01 2009
On Tue, 01 Dec 2009 12:27:07 -0500, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Dec 1, 2009 at 8:58 AM, Steven Schveighoffer <schveiguy yahoo.com> wrote: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.On Tue, 01 Dec 2009 11:24:17 -0500, Bill Baxter <wbaxter gmail.com> wrote:Well with "x in array" syntax you could do void opDispatch(fn : fn in ["foo","bar"])(Variant arg...) {}On Tue, Dec 1, 2009 at 6:30 AM, Steven Schveighoffer <schveiguy yahoo.com> wrote: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...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".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).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
Dec 01 2009
KennyTM~:Make "x in y" returns a bool and works for arrays.That's something more useful than the sum of usefulness of opDispatch, opPow and opLength. You use it all the time in code, and in D it's even more useful than in Python because in D a small linear scan can be very fast. To do that in my dlibs I use the function isIn(item, items), where items can be an AA too of course. Bye, bearophile
Dec 01 2009
bearophile wrote:KennyTM~:I somewhat agree. For small arrays I find it very useful, I use it all the time. compare: if (x in [1, 2, 3]) { } if (x == 1 || x == 2 || x == 3) { } I find the first one prettier. :)Make "x in y" returns a bool and works for arrays.That's something more useful than the sum of usefulness of opDispatch, opPow and opLength. You use it all the time in code, and in D it's even more useful than in Python because in D a small linear scan can be very fast. To do that in my dlibs I use the function isIn(item, items), where items can be an AA too of course. Bye, bearophile
Dec 01 2009