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

2012-05-30 Thread Yike Lu
I just realized that even in the non-nested case, calling from top level 
broke some of my code inexplicably, since the globally stored 
function call gets overridden if you call Curry again. So old Curried 
functions break.


Glad to have this fix.

On 5/25/2012 5:23 PM, Hadley Wickham wrote:



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.


__
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-26 Thread Yike Lu

On 5/25/12 5:23 PM, Hadley Wickham wrote:

On Fri, May 25, 2012 at 3:14 PM, Yike Luyikelu.h...@gmail.com  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.

Yes I could see how one would do that - if the match.call detects a 
Curry as the first function being called, we would short circuit the 
usual evaluation into a different path which properly collapses all the 
nesting.


It's interesting how R offers these facilities to override the usual 
evaluation order, but if one does that too much it could easily become 
confusing. I was looking at Rpipe the other day 
(https://github.com/slycoder/Rpipe) and the way he implements it is by 
defining his own Eval.


Cheers,

__
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-26 Thread Gabor Grothendieck
On Sat, May 26, 2012 at 12:30 PM, Yike Lu yikelu.h...@gmail.com wrote:
 On 5/25/12 5:23 PM, Hadley Wickham wrote:

 On Fri, May 25, 2012 at 3:14 PM, Yike Luyikelu.h...@gmail.com  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.

 Yes I could see how one would do that - if the match.call detects a Curry as
 the first function being called, we would short circuit the usual evaluation
 into a different path which properly collapses all the nesting.

 It's interesting how R offers these facilities to override the usual
 evaluation order, but if one does that too much it could easily become
 confusing. I was looking at Rpipe the other day
 (https://github.com/slycoder/Rpipe) and the way he implements it is by
 defining his own Eval.


The proto package does currying on proto methods by defining $.proto
appropriately:

library(proto)
p - proto(a = 1, b = 2)

# same as ls(p) - output is c(a, b)
p$ls()

Here ls() is _not_ a special proto method but is just the ordinary
ls() provided by R.  $.proto calls ls() sticking in p as the first
argument.  A proto object is an environment and ls with a first
argument that is an environment lists the names of the objects in that
environment.  Similarly:

p$as.list()
p$str()
p$parent.env()
p$print()
p$eapply(length)

are the same as as.list(p), str(p), parent.env(p), print(p) and
eapply(p, length).

Although this might seem like its just syntax in proto it does allow
one to override the method.  For example,

p2 - proto(a = 1, b = 2, print = function(.) with(., cat(a:, a,
b:, b, \n)) )

p2$print() # uses p2's print

print(p2) # uses R's print

etc.

-- 
Statistics  Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com

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


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] Curry: proposed new functional programming, er, function.

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


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

2012-05-24 Thread Yike Lu

Hadley Wickham-2 wrote
 
 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 - as.name(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
 }
 
 But I've probably forgotten something else.  Hopefully Luke will chime
 in if I'm proceeding down a path that can never be made to work
 completely correctly.
 
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).

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

--
View this message in context: 
http://r.789695.n4.nabble.com/Curry-proposed-new-functional-programming-er-function-tp917654p4631127.html
Sent from the R devel mailing list archive at Nabble.com.

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


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

2011-05-25 Thread Peter Danenberg
Sharpie wrote:
 Currently, the only Curry implementation I know of is in the roxygen
 package which is kind of a weird dependency to install just for this
 one function.

I end up using Curry so much outside of Roxygen that I spun it off
into the `functional' package:

  https://r-forge.r-project.org/projects/functional/

Compose is there, too, and a couple other superfluous things.

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


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

2011-05-05 Thread Hadley Wickham
 Thanks, Hadley.  This (i.e., different ways to prepare curry) is quite 
 instructive to me.

The following update makes the generated function look a little nicer
if you pass in the name of a function:

Curry - function(FUN, ...) {
  args - match.call(expand.dots = FALSE)$...
  args$... - as.name(...)

  if (is.name(FUN)) {
fname - FUN
  } else if (is.character(FUN)) {
fname - as.name(FUN)
  } else {
fname - as.name(FUN)
  }
  curry_call - as.call(c(list(fname), args))
  eval(call(function, as.pairlist(alist(... = )), curry_call))
}

And it seems to work ok in terms of preserving evaluation (I can't how
it could be any different to making the anonymous function yourself,
unless I've missed something subtle with environments and scoping)

 hadley - 1:10
 plothadley - Curry(plot, x = hadley)
 plothadley
function (...)
plot(x = hadley, ... = ...)
environment: 0x1031d7c00
 plothadley()
 plothadley(runif(10))

The only (minor) problem is that I couldn't figure out how to
construct the interior call to yield plot(x = hadley, ...)

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


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

2011-05-05 Thread Hadley Wickham
 And it seems to work ok in terms of preserving evaluation (I can't how
 it could be any different to making the anonymous function yourself,
 unless I've missed something subtle with environments and scoping)

Which indeed I have.  Hmmm, need to think about this more.

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


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

2011-05-04 Thread Hadley Wickham
I thought I might bring this up again - it now seems like Curry would
be a natural fit with Reduce, Filter, Find, Map, Negate and Position.
Any chance we might see this in a future version of R?

Hadley

On Thu, Nov 1, 2007 at 2:00 PM, Byron Ellis byron.el...@gmail.com wrote:
 Hi all (especially R-core) I suppose,

 With the introduction of the new functional programming functions into
 base I thought I'd ask for a Curry() function. I use a simple one that
 looks this:

 Curry = function(FUN,...) { .orig = list(...);function(...)
 do.call(FUN,c(.orig,list(...))) }

 This comes in really handy when using say, heatmap():

 heatmap(mydata,hclustfun=Curry(hclust,method=average))

 or other functions where there are ... arguments, but it's not clear
 where they should end up.

 --
 Byron Ellis (byron.el...@gmail.com)
 Oook -- The Librarian

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




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


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

2011-05-04 Thread Ravi Varadhan
I too would like this (being an Indian!).

Here is an example that came up just yesterday with regards to solving a 
quadrature problem using the cubature package.  The adaptIntegrate function 
does not allow additional arguments via ...

Uwe suggested a work around, but `Curry' would solve it nicely (and it also 
tastes better!):

Curry = function(FUN,...) { 
.orig = list(...)
function(...) do.call(FUN,c(.orig, list(...))) 
}

require(cubature)

f - function(x, a) cos(2*pi*x*a)  # a simple test function

# this works
a - 0.2
adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2)

# but this doesn't work
rm(a)
adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2, a=0.2)


# Use of Curry
adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)

Best,
Ravi.

---
Ravi Varadhan, Ph.D.
Assistant Professor,
Division of Geriatric Medicine and Gerontology School of Medicine Johns Hopkins 
University

Ph. (410) 502-2619
email: rvarad...@jhmi.edu


-Original Message-
From: r-devel-boun...@r-project.org [mailto:r-devel-boun...@r-project.org] On 
Behalf Of Hadley Wickham
Sent: Wednesday, May 04, 2011 10:29 AM
To: Byron Ellis
Cc: R Development Mailing List
Subject: Re: [Rd] Curry: proposed new functional programming, er, function.

I thought I might bring this up again - it now seems like Curry would
be a natural fit with Reduce, Filter, Find, Map, Negate and Position.
Any chance we might see this in a future version of R?

Hadley

On Thu, Nov 1, 2007 at 2:00 PM, Byron Ellis byron.el...@gmail.com wrote:
 Hi all (especially R-core) I suppose,

 With the introduction of the new functional programming functions into
 base I thought I'd ask for a Curry() function. I use a simple one that
 looks this:

 Curry = function(FUN,...) { .orig = list(...);function(...)
 do.call(FUN,c(.orig,list(...))) }

 This comes in really handy when using say, heatmap():

 heatmap(mydata,hclustfun=Curry(hclust,method=average))

 or other functions where there are ... arguments, but it's not clear
 where they should end up.

 --
 Byron Ellis (byron.el...@gmail.com)
 Oook -- The Librarian

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




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

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


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

2011-05-04 Thread Duncan Murdoch

On 04/05/2011 10:40 AM, Ravi Varadhan wrote:

I too would like this (being an Indian!).

Here is an example that came up just yesterday with regards to solving a quadrature 
problem using the cubature package.  The adaptIntegrate function does not 
allow additional arguments via ...

Uwe suggested a work around, but `Curry' would solve it nicely (and it also 
tastes better!):

Curry = function(FUN,...) {
.orig = list(...)
function(...) do.call(FUN,c(.orig, list(...)))
}

require(cubature)

f- function(x, a) cos(2*pi*x*a)  # a simple test function

# this works
a- 0.2
adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2)

# but this doesn't work
rm(a)
adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2, a=0.2)


# Use of Curry
adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)


Two objections:

1.  I don't see how that is preferable to

adaptIntegrate(function(x) f(x, a=0.2), lower=0, upper=2)

2.  There seems to be confusion about what currying means.  The 
Wikipedia page http://en.wikipedia.org/wiki/Currying indicates that 
the function Curry() defined above is really doing partial function 
application, not currying.  I'm in no position to judge whether Byron 
got it right or Wikipedia did, but this suggests to me that the name 
Curry is inappropriate, since at least some people who know what 
currying is would not guess that it does what it does.


Duncan Murdoch


Best,
Ravi.

---
Ravi Varadhan, Ph.D.
Assistant Professor,
Division of Geriatric Medicine and Gerontology School of Medicine Johns Hopkins 
University

Ph. (410) 502-2619
email: rvarad...@jhmi.edu


-Original Message-
From: r-devel-boun...@r-project.org [mailto:r-devel-boun...@r-project.org] On 
Behalf Of Hadley Wickham
Sent: Wednesday, May 04, 2011 10:29 AM
To: Byron Ellis
Cc: R Development Mailing List
Subject: Re: [Rd] Curry: proposed new functional programming, er, function.

I thought I might bring this up again - it now seems like Curry would
be a natural fit with Reduce, Filter, Find, Map, Negate and Position.
Any chance we might see this in a future version of R?

Hadley

On Thu, Nov 1, 2007 at 2:00 PM, Byron Ellisbyron.el...@gmail.com  wrote:
  Hi all (especially R-core) I suppose,

  With the introduction of the new functional programming functions into
  base I thought I'd ask for a Curry() function. I use a simple one that
  looks this:

  Curry = function(FUN,...) { .orig = list(...);function(...)
  do.call(FUN,c(.orig,list(...))) }

  This comes in really handy when using say, heatmap():

  heatmap(mydata,hclustfun=Curry(hclust,method=average))

  or other functions where there are ... arguments, but it's not clear
  where they should end up.

  --
  Byron Ellis (byron.el...@gmail.com)
  Oook -- The Librarian

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

2011-05-04 Thread Gabor Grothendieck
On Wed, May 4, 2011 at 10:40 AM, Ravi Varadhan rvarad...@jhmi.edu wrote:
 I too would like this (being an Indian!).

 Here is an example that came up just yesterday with regards to solving a 
 quadrature problem using the cubature package.  The adaptIntegrate function 
 does not allow additional arguments via ...

 Uwe suggested a work around, but `Curry' would solve it nicely (and it also 
 tastes better!):

 Curry = function(FUN,...) {
 .orig = list(...)
 function(...) do.call(FUN,c(.orig, list(...)))
 }

 require(cubature)

 f - function(x, a) cos(2*pi*x*a)  # a simple test function

 # this works
 a - 0.2
 adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2)

 # but this doesn't work
 rm(a)
 adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2, a=0.2)


 # Use of Curry
 adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)


Here is another approach. If we preface any function with gsubfn's fn$
then it will turn formulas (subject to certain rules to determine
which to pay attention to) into functions.

1. Here it is applied to the cubature example

 library(cubature)
 library(gsubfn)
Loading required package: proto

 fn$adaptIntegrate(~ f(x, 0.2), lower=0, upper=2)
$integral
[1] 0.4677446

$error
[1] 1.247382e-14

$functionEvaluations
[1] 15

$returnCode
[1] 0


2. and here is the heatmap example redone.  The example line is to
compute x so that the code is self contained:

library(gsubfn)
example(heatmap)

fn$heatmap(x, hclustfun = ~ hclust(x, method=average))

-- 
Statistics  Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com

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


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

2011-05-04 Thread luke-tierney

On Wed, 4 May 2011, Ravi Varadhan wrote:


I too would like this (being an Indian!).


I would not.


Here is an example that came up just yesterday with regards to solving a quadrature 
problem using the cubature package.  The adaptIntegrate function does not 
allow additional arguments via ...

Uwe suggested a work around, but `Curry' would solve it nicely (and it also 
tastes better!):

Curry = function(FUN,...) {
.orig = list(...)
function(...) do.call(FUN,c(.orig, list(...)))
}


This has quite different behavior with respect to evaluation/lazy
evaluation than an analogous anonymous function. In addition, do.call
has some fairly strange aspect so it with respect to how it intereacts
with sys.xyz functions, and does not do what you want in many cases I
care about when quote = FALSE, as is the default.  Adding this would
create more problems than is solves.


require(cubature)

f - function(x, a) cos(2*pi*x*a)  # a simple test function

# this works
a - 0.2
adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2)


Yes -- as do a number of other variations.


# but this doesn't work
rm(a)
adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2, a=0.2)


Of course not -- why would anyone think it would?




# Use of Curry
adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)


The _concept_ of currying is useful, and maybe more can be done to
provide guidance and education on how to do it, but adding a function
that sometimes works and somesimes does surprising things is not the
way to go.

Best,

luke



Best,
Ravi.

---
Ravi Varadhan, Ph.D.
Assistant Professor,
Division of Geriatric Medicine and Gerontology School of Medicine Johns Hopkins 
University

Ph. (410) 502-2619
email: rvarad...@jhmi.edu


-Original Message-
From: r-devel-boun...@r-project.org [mailto:r-devel-boun...@r-project.org] On 
Behalf Of Hadley Wickham
Sent: Wednesday, May 04, 2011 10:29 AM
To: Byron Ellis
Cc: R Development Mailing List
Subject: Re: [Rd] Curry: proposed new functional programming, er, function.

I thought I might bring this up again - it now seems like Curry would
be a natural fit with Reduce, Filter, Find, Map, Negate and Position.
Any chance we might see this in a future version of R?

Hadley

On Thu, Nov 1, 2007 at 2:00 PM, Byron Ellis byron.el...@gmail.com wrote:

Hi all (especially R-core) I suppose,

With the introduction of the new functional programming functions into
base I thought I'd ask for a Curry() function. I use a simple one that
looks this:

Curry = function(FUN,...) { .orig = list(...);function(...)
do.call(FUN,c(.orig,list(...))) }

This comes in really handy when using say, heatmap():

heatmap(mydata,hclustfun=Curry(hclust,method=average))

or other functions where there are ... arguments, but it's not clear
where they should end up.

--
Byron Ellis (byron.el...@gmail.com)
Oook -- The Librarian

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








--
Luke Tierney
Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa  Phone: 319-335-3386
Department of Statistics andFax:   319-335-3017
   Actuarial Science
241 Schaeffer Hall  email:  l...@stat.uiowa.edu
Iowa City, IA 52242 WWW:  http://www.stat.uiowa.edu

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


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

2011-05-04 Thread Hadley Wickham
 # Use of Curry
 adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)

 The _concept_ of currying is useful, and maybe more can be done to
 provide guidance and education on how to do it, but adding a function
 that sometimes works and somesimes does surprising things is not the
 way to go.

What about an alternative approach?

Curry - function(FUN, ...) {
  args - match.call(expand.dots = FALSE)$...
  args$... - as.name(...)

  curry_call - as.call(c(list(as.name(FUN)), args))
  function(...) {
eval(curry_call)
  }
}

Or maybe

Curry - function(FUN, ...) {
  args - match.call(expand.dots = FALSE)$...
  args$... - as.name(...)

  curry_call - as.call(c(list(as.name(FUN)), args))
  eval(bquote(function(...) .(curry_call)))
}


I think this is pretty close to what you'd get if you made an
anonymous function (but I'm probably missing something)

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


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

2011-05-04 Thread Hadley Wickham
 # Use of Curry
 adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)

 Two objections:

 1.  I don't see how that is preferable to

 adaptIntegrate(function(x) f(x, a=0.2), lower=0, upper=2)

It's less typing?

A more helpful use is when you have a list of functions:

funs - list(
  sum = sum,
  mean = mean,
  median = median
)

with Curry function you can do :

funs2 - lapply(funs, Curry, na.rm = TRUE)

as opposed to

funs2 - list(
  sum = function(x, ...) sum(x, ..., na.rm = TRUE),
  mean = function(x, ...) mean(x, ..., na.rm = TRUE),
  median = function(x, ...) median(x, ..., na.rm = TRUE)
)

 2.  There seems to be confusion about what currying means.  The Wikipedia
 page http://en.wikipedia.org/wiki/Currying indicates that the function
 Curry() defined above is really doing partial function application, not
 currying.  I'm in no position to judge whether Byron got it right or
 Wikipedia did, but this suggests to me that the name Curry is
 inappropriate, since at least some people who know what currying is would
 not guess that it does what it does.

I'm not completely sure that discussion is canonical: wikipedia citing
a blog post does not a precedent make.  I agree the distinction is
sensible, but I think the partial function application sense of
currying is standard enough that it would cause much confusion. We are
not claiming that R has low-level currying, we're creating a function
to simulate a useful property of currying.

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


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

2011-05-04 Thread Hadley Wickham
 Or maybe

    Curry - function(FUN, ...) {
      args - match.call(expand.dots = FALSE)$...
      args$... - as.name(...)

      curry_call - as.call(c(list(as.name(FUN)), args))
      eval(bquote(function(...) .(curry_call)))
    }

Or one more approach:

Curry - function(FUN, ...) {
  args - match.call(expand.dots = FALSE)$...
  args$... - as.name(...)

  curry_call - as.call(c(list(as.name(FUN)), args))
  eval(call(function, as.pairlist(alist(... = )), curry_call))
}

I'm not sure if there's a canonical way of programmatically creating functions.

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


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

2011-05-04 Thread Sharpie

Byron Ellis-2 wrote:
 
 Hi all (especially R-core) I suppose,
 
 With the introduction of the new functional programming functions into
 base I thought I'd ask for a Curry() function. I use a simple one that
 looks this:
 
 Curry = function(FUN,...) { .orig = list(...);function(...)
 do.call(FUN,c(.orig,list(...))) }
 
 ...
 
 

I would like to see this as well---it is one of the functional programming
constructs I really miss in R after playing with languages like Haskell.

Currently, the only Curry implementation I know of is in the roxygen package
which is kind of a weird dependency to install just for this one function.

-Charlie

-
Charlie Sharpsteen
Undergraduate-- Environmental Resources Engineering
Humboldt State University
--
View this message in context: 
http://r.789695.n4.nabble.com/Curry-proposed-new-functional-programming-er-function-tp917654p3496226.html
Sent from the R devel mailing list archive at Nabble.com.

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


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

2011-05-04 Thread Gabor Grothendieck
On Wed, May 4, 2011 at 1:11 PM, Sharpie ch...@sharpsteen.net wrote:
 Currently, the only Curry implementation I know of is in the roxygen package
 which is kind of a weird dependency to install just for this one function.


Not entirely comparable but the proto package supports currying of
proto arguments. For example, p$ls returns an
instantiatedProtoMethod which is an S3 subclass of function that
is like the original method but with the first argument filled in:

 library(proto)
 p - proto(x = 1)
 p$ls()
[1] x


-- 
Statistics  Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com

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


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

2011-05-04 Thread Ravi Varadhan
Thanks, Hadley.  This (i.e., different ways to prepare curry) is quite 
instructive to me.

Best,
Ravi.

---
Ravi Varadhan, Ph.D.
Assistant Professor,
Division of Geriatric Medicine and Gerontology School of Medicine Johns Hopkins 
University

Ph. (410) 502-2619
email: rvarad...@jhmi.edu


-Original Message-
From: h.wick...@gmail.com [mailto:h.wick...@gmail.com] On Behalf Of Hadley 
Wickham
Sent: Wednesday, May 04, 2011 12:01 PM
To: Duncan Murdoch
Cc: Ravi Varadhan; Byron Ellis; R Development Mailing List
Subject: Re: [Rd] Curry: proposed new functional programming, er, function.

 # Use of Curry
 adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)

 Two objections:

 1.  I don't see how that is preferable to

 adaptIntegrate(function(x) f(x, a=0.2), lower=0, upper=2)

It's less typing?

A more helpful use is when you have a list of functions:

funs - list(
  sum = sum,
  mean = mean,
  median = median
)

with Curry function you can do :

funs2 - lapply(funs, Curry, na.rm = TRUE)

as opposed to

funs2 - list(
  sum = function(x, ...) sum(x, ..., na.rm = TRUE),
  mean = function(x, ...) mean(x, ..., na.rm = TRUE),
  median = function(x, ...) median(x, ..., na.rm = TRUE)
)

 2.  There seems to be confusion about what currying means.  The Wikipedia
 page http://en.wikipedia.org/wiki/Currying indicates that the function
 Curry() defined above is really doing partial function application, not
 currying.  I'm in no position to judge whether Byron got it right or
 Wikipedia did, but this suggests to me that the name Curry is
 inappropriate, since at least some people who know what currying is would
 not guess that it does what it does.

I'm not completely sure that discussion is canonical: wikipedia citing
a blog post does not a precedent make.  I agree the distinction is
sensible, but I think the partial function application sense of
currying is standard enough that it would cause much confusion. We are
not claiming that R has low-level currying, we're creating a function
to simulate a useful property of currying.

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


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

2011-05-04 Thread baptiste auguie
Hi,

On 5 May 2011 02:56, Duncan Murdoch murdoch.dun...@gmail.com wrote:
 On 04/05/2011 10:40 AM, Ravi Varadhan wrote:

 I too would like this (being an Indian!).

 Here is an example that came up just yesterday with regards to solving a
 quadrature problem using the cubature package.  The adaptIntegrate
 function does not allow additional arguments via ...

 Uwe suggested a work around, but `Curry' would solve it nicely (and it
 also tastes better!):

 Curry = function(FUN,...) {
 .orig = list(...)
 function(...) do.call(FUN,c(.orig, list(...)))
 }

 require(cubature)

 f- function(x, a) cos(2*pi*x*a)  # a simple test function

 # this works
 a- 0.2
 adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2)

 # but this doesn't work
 rm(a)
 adaptIntegrate(function(x, argA=a) f(x, a=argA), lower=0, upper=2, a=0.2)


 # Use of Curry
 adaptIntegrate(Curry(f, a=0.2), lower=0, upper=2)

 Two objections:

 1.  I don't see how that is preferable to

 adaptIntegrate(function(x) f(x, a=0.2), lower=0, upper=2)

In this particular case I don't think it is. The reason I proposed it
yesterday for the cubature example was that in some cases it can make
the code more concise and clearer in my opinion. This is the case when
you override a considerable number of arguments in a function.

Consider this,

read.table2 = Curry(read.table, header = TRUE, na.strings = ,
colClasses = numeric, nrows = 23)

vs

read.table2 = function(..., header = TRUE, na.strings = ,
colClasses = numeric, nrows = 23)
{
 read.table(header = header, na.strings = na.strings,
   colClasses = colClasses, nrows = nrows, ...)
}

Whether or not this should be called curry, I have no idea. In any
case it seems like a useful function to have in a base package,
regardless of its implementation details.

baptiste



 2.  There seems to be confusion about what currying means.  The Wikipedia
 page http://en.wikipedia.org/wiki/Currying indicates that the function
 Curry() defined above is really doing partial function application, not
 currying.  I'm in no position to judge whether Byron got it right or
 Wikipedia did, but this suggests to me that the name Curry is
 inappropriate, since at least some people who know what currying is would
 not guess that it does what it does.

 Duncan Murdoch

 Best,
 Ravi.

 ---
 Ravi Varadhan, Ph.D.
 Assistant Professor,
 Division of Geriatric Medicine and Gerontology School of Medicine Johns
 Hopkins University

 Ph. (410) 502-2619
 email: rvarad...@jhmi.edu


 -Original Message-
 From: r-devel-boun...@r-project.org [mailto:r-devel-boun...@r-project.org]
 On Behalf Of Hadley Wickham
 Sent: Wednesday, May 04, 2011 10:29 AM
 To: Byron Ellis
 Cc: R Development Mailing List
 Subject: Re: [Rd] Curry: proposed new functional programming, er,
 function.

 I thought I might bring this up again - it now seems like Curry would
 be a natural fit with Reduce, Filter, Find, Map, Negate and Position.
 Any chance we might see this in a future version of R?

 Hadley

 On Thu, Nov 1, 2007 at 2:00 PM, Byron Ellisbyron.el...@gmail.com  wrote:
   Hi all (especially R-core) I suppose,
 
   With the introduction of the new functional programming functions into
   base I thought I'd ask for a Curry() function. I use a simple one that
   looks this:
 
   Curry = function(FUN,...) { .orig = list(...);function(...)
   do.call(FUN,c(.orig,list(...))) }
 
   This comes in really handy when using say, heatmap():
 
   heatmap(mydata,hclustfun=Curry(hclust,method=average))
 
   or other functions where there are ... arguments, but it's not clear
   where they should end up.
 
   --
   Byron Ellis (byron.el...@gmail.com)
   Oook -- The Librarian
 
   __
   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


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


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

2007-11-01 Thread Byron Ellis
Hi all (especially R-core) I suppose,

With the introduction of the new functional programming functions into
base I thought I'd ask for a Curry() function. I use a simple one that
looks this:

Curry = function(FUN,...) { .orig = list(...);function(...)
do.call(FUN,c(.orig,list(...))) }

This comes in really handy when using say, heatmap():

heatmap(mydata,hclustfun=Curry(hclust,method=average))

or other functions where there are ... arguments, but it's not clear
where they should end up.

-- 
Byron Ellis ([EMAIL PROTECTED])
Oook -- The Librarian

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