Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to curry a ... argument by position in R?

Tags:

r

currying

This may fall under "you can't, and there's no reason to anyway," but I'm curious if it's possible. At very least, maybe it will be a fun R puzzle.

I was pondering currying cat to always append \n. However, cat is written so that it pastes together as many arguments as it is given (via ...).

Surprisingly, this works:

> library(functional)
> catnip <- Curry( cat, "\n" )
> catnip("hi")

 hi

However, the \n winds up before the user's text. Is there any way to curry the function such that you specify the curried argument always ends the ... arguments?

like image 839
Ari B. Friedman Avatar asked Jun 27 '12 18:06

Ari B. Friedman


People also ask

How to write a curry function?

The following basic example uses currying. function multiply(a, b, c) { return a * b * c; } function multiply_curried(a) { return function (b) { return function (c) { return a * b * c } } } let res = multiply(1, 2, 3); console. log(res); let mc1 = multiply_curried(1); let mc2 = mc1(2); let res2 = mc2(3); console.

What is curry in R?

curry: Partial Function Application with %<%, %-<%, and %><% Partial application is the process of reducing the arity of a function by fixing one or more arguments, thus creating a new function lacking the fixed arguments.

How do curried functions work?

A curried function is a function that takes multiple arguments one at a time. Given a function with 3 parameters, the curried version will take one argument and return a function that takes the next argument, which returns a function that takes the third argument.

What is currying and composition?

Composition and currying are used to create functions. Composition and currying differ in the way they create new functions (by applying args vs chaining). Compose: Compose should return a function that is the composition of a list of functions of arbitrary length.


2 Answers

Looks like Curry() pretty effectively hardwires the two argument lists in the opposite order from what you'd like. It's a simple enough function though, that you can just construct its mirror image, and use it instead.

Curry2 <- function(FUN, ...) {
    .orig = list(...)
    function(...) do.call(FUN, c(list(...), .orig))
}

catnip <- Curry2( cat, "\n" )
catnip("hi")
like image 166
Josh O'Brien Avatar answered Sep 27 '22 20:09

Josh O'Brien


#1. Ignore the second argument of Curry and hard code the newline

Try this which curries the last argument of cat by hard coding it in an anonymous function. It does not actually make use of Curry arguments after the first:

catnip <- Curry(function(...) cat(..., "\n") )

#2. Manufacture function by currying an anonymous function

Here is a second solution which curries the last argument of cat by using an anonymous function which reorders cat's arguments.

catnip2 <- Curry(function(last.arg, ...) cat(..., last.arg), "\n")

# test
catnip2("hi", "there")

#3. Manufacture desired function by currying an even more basic function

Perhaps the real point of all this is to see how we can take basic components and Curry them to get what we want. Thus we could define a general last.arg.fun and then manufacture the desired function by a curry of it:

last.arg.fun <- function(FUN, last.arg, ...) FUN(..., last.arg)
catnip3 <- Curry(last.arg.fun, cat, "\n")

# test
last.arg.fun(cat, "\n", "hi", "there")

# test
catnip3("hi", "there")

We could do it in two steps if we needed last.arg.cat at some point:

last.arg.cat <- Curry(last.arg.fun, cat)
catnip4 <- Curry(last.arg.cat, "\n")

# test
last.arg.cat("\n", "hi", "there")

# test
catnip4("hi", "there")

Note that each of the tests should produce a line saying hi there ended in a newline.

EDIT: more solutions.

like image 39
G. Grothendieck Avatar answered Sep 27 '22 19:09

G. Grothendieck