No, we are not talking about dinner, although this post is giving me ideas about what I should have for lunch.
Basically, you take a function of multiple arguments and reduce it to a function with one argument. I probably use the term incorrectly, because I also consider currying to cover any reduction in the number of function arguments, not just down to one.
Here’s an example. I’m using the
from my personal R package.
library(alrtools) my_rnorm <- curry(rnorm, mean = 100, sd = 200) print(my_rnorm) ## function (n, mean = 100, sd = 200) ## .Call(C_rnorm, n, mean, sd) ## <environment: namespace:stats>
Now, every time I use
my_rnorm the parameters
sd are pre-set.
set.seed(95) x <- my_rnorm(100e3) mean(x) ##  99.52828 sd(x) ##  199.7653
curry function still get a weird error with some functions
that are very general in the arguments they accept, like
I’m still figuring that out.
There are other packages in R that support currying.
library(functional) f_rnorm <- Curry(rnorm, mu = -20, sd = 35) print(f_rnorm) ## function (...) ## do.call(FUN, c(.orig, list(...))) ## <environment: 0x0000000018982178>
Peter Danenberg, the author of the
credits Byron Ellis
I have an older version of
that I copied from the same source. Fun times.
So, if this has existed since 2007,
why am I blogging about it?
Because I finally solved something annoying about
and I just can’t wait to share (with the two people who will read this).
Check out the function signatures for the two curried functions and the original:
args(f_rnorm) ## function (...) args(my_rnorm) ## function (n, mean = 100, sd = 200) args(rnorm) ## function (n, mean = 0, sd = 1)
f_rnorm doesn’t tell you anything about the arguments that are left,
or the defaults that were set in the currying process.
Most of the time, no one cares because you just created the curried function
so why should you have forgotten the details about it?
Yes, true, but I want to use
alrtools::curry to provide code for other
people to use, and they might like the visual cues.
Here are some cool things about my new version of
- The function signature shows all arguments
- Currying changes the function signature and simply includes defaults for the curried arguments
- You can add new arguments that before were not in the signature!
- You can override the curried arguments if you want (because the currying is done by specifying default values instead of storing the default values in the closure)
- The new function stays in the namespace of the original function, but is still listed in the global environment
- But, remember the caveat I gave above – I am still working through all the issues with
- I haven’t tested this yet, but I am pretty sure that curried arguments will be able to reference other arguments, like in the function signature of
Just a note for those of you who like this topic but would rather use
a more reputable package, like
functional. You can still get at
all the information you want within the function closure.
R let’s you examine those, and I will show you how.
(Also, my package is licensed as CC0, so you can steal the code
and use it wherever you want, too. I don’t care. Attribution is nice.)
max100 <- functional::Curry(max, 100) max100(c(40, 20, -21)) ##  100 max100(150, 34, -132) ##  150 ls(environment(max100), all.names = TRUE) ##  "..." ".orig" "FUN" environment(max100)$.orig ## [] ##  100 environment(max100)$FUN ## function (..., na.rm = FALSE) .Primitive("max")
Thanks for reading!