3

If have a function that returns a function:

makeFunction <- function (d) {
    function (x) { x/d }
}

f <- makeFunction(2)
print(f)
# function (x) { x/d }
# <environment: 0x34216b8>
f(4) # 2, as expected

What I want is to have f simply "be" function (x) { x/2 }. By "be", I mean that it doesn't carry that environment around (with the value of d in it), and when I print it, it shows function (x) { x/2 }. Is such a thing possible?


Attempts so far

I can get almost there with substitute:

makeFunction.sub <- function (d) {
    substitute(function (x) { x/d }, list(d=d))
}
g <- makeFunction.sub(2)
print(g)
# function(x) {
#     x/2
# }

However, g is not a function - it's a call. So to get the function I need to eval it. But then it loses the 2 and reverts to d:

eval(g)
# function (x) { x/d }

Is there any way I can make the returned function forget about d and just substitute 2 directly?

(In practice, I don't mind carrying around the environment, but I was just curious...)


Solution

Going to mark as dupe (well, subset) of this question/answer (thanks @joran).

That question & answer are much more detailed, so for the record:

makeFunction <- function (d) {
    of <- function (x) {}
    # do the substitution of d in the body
    body(of) <- substitute(x/d, list(d=d))
    # don't need to carry around the little local environment anymore
    environment(of) <- .GlobalEnv
    return(of)
}
h <- makeFunction(2)
print(h)
# function (x) 
# x/2
Community
  • 1
  • 1
mathematical.coffee
  • 55,977
  • 11
  • 154
  • 194
  • Is anything here useful? http://stackoverflow.com/a/12983961/324364 – joran Sep 08 '15 at 04:11
  • ooo, probably! cheers, will have a read (my lack of knowledge makes it hard to do an intelligent search for these questions) – mathematical.coffee Sep 08 '15 at 04:29
  • some good theory to read is here: http://adv-r.had.co.nz/Functional-programming.html#closures – Chris Nov 26 '15 at 19:04
  • and a helpful function beyond the link is `pryr::unenclose`. You can then do something like `f <- pryr::unenclose(makeFunction(2))` – Chris Nov 26 '15 at 19:07

0 Answers0