digitalmars.D.learn - Operators as function arguments?
- Falk Henrich (27/27) Mar 23 2007 Hi!
- Chris Nicholson-Sauls (17/62) Mar 23 2007 None, frankly. Although, with the upcoming macros feature, you might be...
- Falk Henrich (4/10) Mar 24 2007 That would be a killer feature that's useful for a lot more than my
- Daniel Keep (26/69) Mar 23 2007 Like Chris said, there's really no way to get what you want in this
- Falk Henrich (12/25) Mar 24 2007 That's what I'm doing now. It's like a yoga ;-)
- Jarrett Billingsley (23/24) Mar 24 2007 Perhaps?
- Daniel Keep (14/47) Mar 24 2007 Interesting. I'd never thought of doing it that way. :)
Hi! I'm trying to do some functional programming in D and came across the following problems: Can I somehow use the built-in operator ~ as an argument to a function? The doc [1] seems to say no as operator overloading is implemented by adding a non-static member function to some class. It would avoid lots of repetitive definitions of anonymous delegates. The following example uses reduce from [2]: int[][] a; int[] b; b = reduce(a, (int[] x, int[] y){return x~y;}); Now it would be useful to do b = reduce(a,~); It would be even nicer to define "flatten" using templates to avoid code duplication for different types of arrays. I tried to define T[] cat(T)(T[] a, T[] b) { return a ~ b; } but then b = reduce(a, &cat); yields cat(T) is not an lvalue The only workaround seems to be to explicitly instantiate the template function: alias cat!(int) catInt; b = reduce(a, &catInt); But this is extremely clumsy. Any idea? Falk [1] http://www.digitalmars.com/d/operatoroverloading.html [2] http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/functools
Mar 23 2007
Falk Henrich wrote:Hi! I'm trying to do some functional programming in D and came across the following problems: Can I somehow use the built-in operator ~ as an argument to a function? The doc [1] seems to say no as operator overloading is implemented by adding a non-static member function to some class. It would avoid lots of repetitive definitions of anonymous delegates. The following example uses reduce from [2]: int[][] a; int[] b; b = reduce(a, (int[] x, int[] y){return x~y;}); Now it would be useful to do b = reduce(a,~); It would be even nicer to define "flatten" using templates to avoid code duplication for different types of arrays. I tried to define T[] cat(T)(T[] a, T[] b) { return a ~ b; } but then b = reduce(a, &cat); yields cat(T) is not an lvalue The only workaround seems to be to explicitly instantiate the template function: alias cat!(int) catInt; b = reduce(a, &catInt); But this is extremely clumsy. Any idea? Falk [1] http://www.digitalmars.com/d/operatoroverloading.html [2] http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/functoolsNone, frankly. Although, with the upcoming macros feature, you might be able to do something like this: macro binop (Type, Op) { (Type x, Type y) { return x Op y; } } b = reduce(a, binop(int[], ~)); Although, heck, you might be able to write reduce itself as a macro passing the operator you want to it then. macro reduce (Val, Op) { //... } b = reduce(a, ~); Which, come to think of it, is basically what you wanted in the first place!...except that it isn't, because macros are always inlined. Best I could come up with off the top my head, though, and reliant on as yet unreleased features. -- Chris Nicholson-Sauls
Mar 23 2007
Chris Nicholson-Sauls wrote:None, frankly. Although, with the upcoming macros feature, you might be able to do something like this: macro binop (Type, Op) { (Type x, Type y) { return x Op y; } }That would be a killer feature that's useful for a lot more than my "operator as argument" problem. Falk
Mar 24 2007
Falk Henrich wrote:Hi! I'm trying to do some functional programming in D and came across the following problems: Can I somehow use the built-in operator ~ as an argument to a function? The doc [1] seems to say no as operator overloading is implemented by adding a non-static member function to some class. It would avoid lots of repetitive definitions of anonymous delegates. The following example uses reduce from [2]: int[][] a; int[] b; b = reduce(a, (int[] x, int[] y){return x~y;}); Now it would be useful to do b = reduce(a,~); It would be even nicer to define "flatten" using templates to avoid code duplication for different types of arrays. I tried to define T[] cat(T)(T[] a, T[] b) { return a ~ b; } but then b = reduce(a, &cat); yields cat(T) is not an lvalue The only workaround seems to be to explicitly instantiate the template function: alias cat!(int) catInt; b = reduce(a, &catInt); But this is extremely clumsy. Any idea? FalkLike Chris said, there's really no way to get what you want in this case. D is not Haskell, so we just have to make lots of delegates :P Way back when I first started using D, I actually wrote up a bunch of templates that defined delegates for every unary and binary operator, and a bunch of templated tests (like less-than, equal-to, etc.). Re: your cat template above, you should be able to do this: b = reduce(a, &cat!(int)); Which saves you from having to define the alias. Also as Chris said, macros may save the day, but they will likely be a while in coming: D2.0 is looking bigger and bigger every day :P The way I look at functional programming in D is basically: It's not as good as a *real* functional programming language, but boy does it beat Anyway, hope this helps some.[1] http://www.digitalmars.com/d/operatoroverloading.html [2] http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/functoolsOh, you have no idea how much of a kick it is to see that link. ^_^ -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 23 2007
Daniel Keep wrote:Like Chris said, there's really no way to get what you want in this case. D is not Haskell, so we just have to make lots of delegates :PI agree although I actually don't know Haskell that much, only Opal ([1]).Way back when I first started using D, I actually wrote up a bunch of templates that defined delegates for every unary and binary operator, and a bunch of templated tests (like less-than, equal-to, etc.).That's what I'm doing now. It's like a yoga ;-)Re: your cat template above, you should be able to do this: b = reduce(a, &cat!(int));Thanks. That makes the thing a bit less wordy.The way I look at functional programming in D is basically: It's not as good as a *real* functional programming language, but boy does it beatTrue. I think the ability to mix different paradigms in D is really good. None of the pure functional languages will get widely accepted as there's no decent I/O. On the other hand, things like HOF reduce code length and bugginess by a factor. So it's a really good idea to get the good stuff from FP without restricting to it.It's a good example for D's "static if" and similar features. Falk [1] http://uebb.cs.tu-berlin.de/~opal/[2] http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/functoolsOh, you have no idea how much of a kick it is to see that link. ^_^
Mar 24 2007
"Falk Henrich" <schreibmalwieder hammerfort.de> wrote in message news:eu1cm8$k2i$1 digitalmars.com...But this is extremely clumsy. Any idea?Perhaps? typeof(a[0]) reduce(alias a, alias func)() { auto ret = a[0]; foreach(v; a[1 .. $]) ret = func(ret, v); return ret; } T[] cat(T)(T[] a, T[] b) { return a ~ b; } void main() { int[][] a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; int[] b; b = reduce!(a, cat)(); writefln(b); } Using the alias parameter for the function means you can no longer use delegate literals for the function, but..
Mar 24 2007
Jarrett Billingsley wrote:"Falk Henrich" <schreibmalwieder hammerfort.de> wrote in message news:eu1cm8$k2i$1 digitalmars.com...Interesting. I'd never thought of doing it that way. :) I do actually use the delegate literals in a few places, tho, so it would likely annoy me... plus, having !(...)() looks hackish. :P -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/But this is extremely clumsy. Any idea?Perhaps? typeof(a[0]) reduce(alias a, alias func)() { auto ret = a[0]; foreach(v; a[1 .. $]) ret = func(ret, v); return ret; } T[] cat(T)(T[] a, T[] b) { return a ~ b; } void main() { int[][] a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; int[] b; b = reduce!(a, cat)(); writefln(b); } Using the alias parameter for the function means you can no longer use delegate literals for the function, but..
Mar 24 2007