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

2012-05-25 Thread Hadley Wickham
> I've been playing around with this for a while. One flaw I found - it
> doesn't handle nested Curries very well (the naive implementation in
> roxygen/functional does).

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

-- 
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


[Rd] equivalent to source() inside a package

2012-05-25 Thread Wei Hao
Hi all:

I'm working on a project that I have packaged for ease of
distribution. The different simulations in the package share code, so
obviously I have those parts organized as functions. Now, I want to
show people my code, but the structure with the internal functions
might be a little confusing to follow. One thing I tried was to have
the code of the functions as their own R files in the R/ folder, and
then using source() instead of calling the functions (with consistent
variable names and such) but this didn't work. The goal is for the
user to be able to see the entirety of the code in the interactive R
session, i.e. with a standard package implementation:

> library(wei.simulations)
> sim1
function (seed=)
{
[stuff]
a = internal_function1(data)
[stuff]
}



I would like the user to see:

> sim1
function (seed=)
{
[stuff]
tmp = apply(data,1,mean)
a = sum(tmp) #or whatever, this is just an example
[stuff]
}

where I can change those two lines in their own file, and have the
changes apply for all the simulation functions. I know this seems like
a weird question to ask, but it would be useful for me to make it as
foolproof as possible for the user to see all the simulation code (I'm
presuming the user is a casual R user and not familiar with looking
through package sources).

Thanks
Wei

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2012-05-25 Thread Yike Lu

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@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] equivalent to source() inside a package

2012-05-25 Thread Paul Gilbert
Is there a reason for not using a vignette or putting a file in the 
demo/  directory?  This seems like the sort of thing for which they are 
intended.


Paul

On 12-05-25 03:33 PM, Wei Hao wrote:

Hi all:

I'm working on a project that I have packaged for ease of
distribution. The different simulations in the package share code, so
obviously I have those parts organized as functions. Now, I want to
show people my code, but the structure with the internal functions
might be a little confusing to follow. One thing I tried was to have
the code of the functions as their own R files in the R/ folder, and
then using source() instead of calling the functions (with consistent
variable names and such) but this didn't work. The goal is for the
user to be able to see the entirety of the code in the interactive R
session, i.e. with a standard package implementation:


library(wei.simulations)
sim1

function (seed=)
{
 [stuff]
 a = internal_function1(data)
 [stuff]
}



I would like the user to see:


sim1

function (seed=)
{
 [stuff]
 tmp = apply(data,1,mean)
 a = sum(tmp) #or whatever, this is just an example
 [stuff]
}

where I can change those two lines in their own file, and have the
changes apply for all the simulation functions. I know this seems like
a weird question to ask, but it would be useful for me to make it as
foolproof as possible for the user to see all the simulation code (I'm
presuming the user is a casual R user and not familiar with looking
through package sources).

Thanks
Wei

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2012-05-25 Thread Hadley Wickham
On Fri, May 25, 2012 at 3:14 PM, Yike Lu  wrote:
> 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.

Yup.  With a bit more infrastructure you could probably modify it so
that multiple curries collapsed into the equivalent single curry.

> 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.

Yes, that was a really bad idea - not sure why I didn't see the
problems when I first wrote it.

> 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

I can see why that's useful at the language level, but I think it
would be confusing to do so in R.

Hadley

-- 
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel