Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
March 23, 2007 Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
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 |
March 23, 2007 Re: Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Falk Henrich | 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/functools
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; }
}
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
|
March 24, 2007 Re: Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Falk Henrich | 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 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 :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 the pants off C/C++/Java/C#/etc.! Anyway, hope this helps some. > [1] http://www.digitalmars.com/d/operatoroverloading.html > [2] http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/functools Oh, 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/ |
March 24, 2007 Re: Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | 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
|
March 24, 2007 Re: Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | 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 :P I 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 beat the pants off C/C++/Java/C#/etc.! True. 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. >> [2] http://www.prowiki.org/wiki4d/wiki.cgi?DanielKeep/functools > > Oh, you have no idea how much of a kick it is to see that link. ^_^ It's a good example for D's "static if" and similar features. Falk [1] http://uebb.cs.tu-berlin.de/~opal/ |
March 24, 2007 Re: Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Falk Henrich | "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.. |
March 25, 2007 Re: Operators as function arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley wrote: > "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.. 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/ |
Copyright © 1999-2021 by the D Language Foundation