Re: [Rd] Curry: proposed new functional programming, er, function.

From: Yike Lu <yikelu.home_at_gmail.com>
Date: Fri, 25 May 2012 16:14:08 -0400

So here's the way I'm reading this:

Original:
curry_call is the function body you're constructing, which is itself just a one liner which calls the symbol FUN with the appropriate substitutions.

call("function", [...]) calls the "function" function, which itself takes 2 arguments: the list of formal args and the function body. eval of this call returns the newly constructed function, which you assign to f. Then you assign the parent.frame() as the environment of f, except with the symbol FUN assigned as the original argument FUN.

However, upon looking at the debugger, I find that env$FUN<-FUN assigns FUN in Global Scope if Curry is called from the top level. A nested Curry call then creates FUN=function(...) FUN([...]), a recursive infinite loop.

New:
The recursion is obviously removed now, but what's the new version do?

As far as I can tell, it returns a structure like...

function(...){function(...) {original_function_body(curried_arg, ...=...)}}

Comparing and contrasting to the version in "functional" package: 1) quotes work (can do Curry(quote(foo), 2) where the "functional" version can't)
2) environment capture works in both constructions 3) Your new version is exceptionally transparent, as the function body gets stored so that when you print the body later, you can see the original

As far as 0 argument functions, I understand the difference, that idea came from a programming language (q/kdb+) I know that supports a neat compact syntax for this:

Suppose in R the function was f(x,y,z) x + y + z

In q, one could do:
f[1;2] // returns the curried form
f[1;2] each (1 2 3 4 5) // equivalent to Map(function(z) f(1,2,z), 1:5) or Map(Curry(f, 1, 2), 1:5)
f[1;2;3] // returns 6
f[1;2][3] // returns 6

Probably a slightly different but related concept - elided arguments, just a curry with automatic eval when all argument slots are filled.

Thanks, this has been very enlightening.

Yike

On 5/25/2012 9:49 AM, Hadley Wickham wrote:
>
> That's easily fixed:
>
> Curry<- function(FUN, ...) {
> args<- match.call(expand.dots = FALSE)$...
> args$...<- as.name("...")
>
> env<- parent.frame()
>
> if (is.name(FUN)) {
> fname<- FUN
> } else if (is.character(FUN)) {
> fname<- as.name(FUN)
> } else if (is.function(FUN)){
> fname<- FUN
> # env$FUN<- FUN
> } else {
> stop("FUN not function or name of function")
> }
> curry_call<- as.call(c(list(fname), args))
>
> f<- eval(call("function", as.pairlist(alist(... = )), curry_call))
> environment(f)<- env
> f
> }
>
>
> Curry(Curry(foo,3),4)
>
>> e.g.:
>>
>> foo=function(x,y,z) x+y+z
>> Curry(Curry("foo",3),4)(3)
>> # 10
>>
>> Curry(Curry(foo,3),4)(3)
>> # hangs
>>
>> foo4=function(a,b,c,d)
>> Curry(Curry(Curry("foo4",3),4),1)(3)
>> # hangs
>>
>> I was also curious if there was some trick to force a function eval when the
>> list of arguments got exhausted (for example, a triple Curry on foo above
>> would leave no arguments so would trigger eval into 10).
>
> I don't think that would be a good idea - there's a big difference
> between a function with no arguments and the result of calling that
> function.
>
> Hadley
>



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Fri 25 May 2012 - 20:17:50 GMT

This quarter's messages: by month, or sorted: [ by date ] [ by thread ] [ by subject ] [ by author ]

All messages

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Fri 25 May 2012 - 21:32:05 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive