Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
July 27, 2014 Currying and composition | ||||
---|---|---|---|---|
| ||||
In std.functional there is a curry(), that looks more like a partial application. In the Python land I've recently seen a library for a more functional style of coding: https://pypi.python.org/pypi/PyMonad/ I don't like for Python most of the stuff in that PyMonad library, but two bits look nice. I quote them here: << @curry def add(x, y): return x + y @curry def func(x, y, z): # Do something with x, y and z. ... The above fuctions can be partially applied by passing them less than their full set of arguments: add(7, 8) # Calling 'add' normally returns 15 as expected. add7 = add(7) # Partial application: 'add7' is a function taking one argument. add7(8) # Applying the final argument retruns 15... add7(400) # ... or 407, or whatever. # 'func' can be applied in any of the following ways. func(1, 2, 3) # Call func normally. func(1, 2)(3) # Partially applying two, then applying the last argument. func(1)(2, 3) # Partially applying one, then applying the last two arguments. func(1)(2)(3) # Partially applying one, partially applying again, then applying the l Curried functions can be composed with the * operator. Functions are applied from right to left: # Returns the first element of a list. @curry def head(aList): return aList[0] # Returns everything except the first element of the list. @curry def tail(aList): return aList[1:] second = head * tail # 'tail' will be applied first, then its result passed to 'head' second([1, 2, 3, 4]) # returns 2 You can also compose partially applied functions: @curry def add(x, y): return x + y @curry def mul(x, y): return x * y comp = add(7) * mul(2) # 'mul(2)' is evaluated first, and it's result passed to 'add(7)' comp(4) # returns 15 >> Perhaps I'd like in Phobos a "curry" (or another name) template that returns a callable struct that allows both those operations: the currying with arbitrary partial application and the "*" operator to perform function composition (I think the two pieces of functionality go well together despite being different things, because they are both used in a very functional style of coding). Bye, bearophile |
July 27, 2014 Re: Currying and composition | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 07/27/2014 10:48 AM, bearophile wrote: > In std.functional there is a curry(), that looks more like a partial application. > > In the Python land I've recently seen a library for a more functional style of coding: https://pypi.python.org/pypi/PyMonad/ > > I don't like for Python most of the stuff in that PyMonad library, but two bits look nice. I quote them here: > > << > > @curry > def add(x, y): > return x + y > > @curry > def func(x, y, z): > # Do something with x, y and z. > ... > > The above fuctions can be partially applied by passing them less than their full set of arguments: > > add(7, 8) # Calling 'add' normally returns 15 as expected. > add7 = add(7) # Partial application: 'add7' is a function taking one argument. > add7(8) # Applying the final argument retruns 15... > add7(400) # ... or 407, or whatever. > > # 'func' can be applied in any of the following ways. > func(1, 2, 3) # Call func normally. > func(1, 2)(3) # Partially applying two, then applying the last argument. > func(1)(2, 3) # Partially applying one, then applying the last two arguments. > func(1)(2)(3) # Partially applying one, partially applying again, then applying the l > > > > Curried functions can be composed with the * operator. Functions are applied from right to left: > > # Returns the first element of a list. > @curry > def head(aList): > return aList[0] > > # Returns everything except the first element of the list. > @curry > def tail(aList): > return aList[1:] > > second = head * tail # 'tail' will be applied first, then its result passed to 'head' second([1, 2, 3, 4]) # returns 2 > > > You can also compose partially applied functions: > > @curry > def add(x, y): > return x + y > > @curry > def mul(x, y): > return x * y > > comp = add(7) * mul(2) # 'mul(2)' is evaluated first, and it's result passed to 'add(7)' > comp(4) # returns 15 > >>> > > > Perhaps I'd like in Phobos a "curry" (or another name) template that returns a callable struct that allows both those operations: the currying with arbitrary partial application and the "*" operator to perform function composition (I think the two pieces of functionality go well together despite being different things, because they are both used in a very functional style of coding). > > Bye, > bearophile So, in the next release std.functional.curry has been renamed to std.functional.partial: https://github.com/D-Programming-Language/phobos/pull/1979 I was starting to work on a proper curry replacement, but due to some real-life stuff I haven't had time. There's some starting code at https://issues.dlang.org/show_bug.cgi?id=4391 that I was basing mine off of, but I was running into some issues involving static, and a ton of issues with templated functions. This might be something worth looking into? -- Matt Soucy http://msoucy.me/ -- Matt Soucy http://msoucy.me/ |
July 27, 2014 Re: Currying and composition | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matt Soucy | Matt Soucy: > So, in the next release std.functional.curry has been renamed to std.functional.partial: > > https://github.com/D-Programming-Language/phobos/pull/1979 Oh, good. (And the "sigh" by Andrei is cute). > I was starting to work on a proper curry replacement, Is its syntax usage similar to the one I've shown for Python? func(1, 2, 3) func(1, 2)(3) func(1)(2, 3) func(1)(2)(3) Is it a good idea to also mix in the function composition operator overloading? Bye, bearophile |
July 27, 2014 Re: Currying and composition | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 07/27/2014 12:09 PM, bearophile wrote: > Matt Soucy: > >> So, in the next release std.functional.curry has been renamed to std.functional.partial: >> >> https://github.com/D-Programming-Language/phobos/pull/1979 > > Oh, good. (And the "sigh" by Andrei is cute). > I was hoping that was a "sigh, alright I guess this is something we sould do" > >> I was starting to work on a proper curry replacement, > > Is its syntax usage similar to the one I've shown for Python? > > func(1, 2, 3) > func(1, 2)(3) > func(1)(2, 3) > func(1)(2)(3) > Mine didn't get very far, but the goal was to have that behavior > Is it a good idea to also mix in the function composition operator overloading? I'm not so sure about that one - mainly because then it's possible with some functions (the curried ones) but not all (including "regular" and delegates). -- Matt Soucy http://msoucy.me/ |
July 27, 2014 Re: Currying and composition | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matt Soucy | Matt Soucy:
>> Is it a good idea to also mix in the function composition operator overloading?
>
> I'm not so sure about that one - mainly because then it's possible with some functions (the curried ones) but not all (including "regular" and delegates).
If you compose (multiply) a "curried" with a regular or a regular with a "curried", you produce a "curried". Is this a problem and not enough?
Bye,
bearophile
|
July 27, 2014 Re: Currying and composition | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 07/27/2014 04:59 PM, bearophile wrote: > Matt Soucy: > >>> Is it a good idea to also mix in the function composition operator overloading? >> >> I'm not so sure about that one - mainly because then it's possible with some functions (the curried ones) but not all (including "regular" and delegates). > > If you compose (multiply) a "curried" with a regular or a regular with a "curried", you produce a "curried". Is this a problem and not enough? > > Bye, > bearophile Try to compose a regular and a regular. If you expect them to all work the same, you're in for a surprise. -- Matt Soucy http://msoucy.me/ |
Copyright © 1999-2021 by the D Language Foundation