2015-11-06 4 views
1

Внутри функции, как мы можем надежно вернуть объект, который содержит эту функцию?Доступ к функции, вызываемой из функции

Например с:

functionBuilder <- function(wordToSay) { 
    function(otherWordToSay) { 
    print(wordToSay) 
    print(otherWordToSay) 
    get(as.character(match.call()[[1]])) 
    } 
} 

Я могу построить функцию, как так:

functionToRun <- functionBuilder("hello nested world")

... и запустить его ...

functionToRun("A") 
#[1] "hello nested world" 
#[1] "A" 
# 
#function(otherWordToSay) { 
#  print(wordToSay) 
#  print(otherWordToSay) 
#  get(as.character(match.call()[[1]])) 
#  } 
#<environment: 0x1e313678> 

.. как вы видите, functionToRun сам возвращается. Однако, такой подход, как представляется, сломаться, если я называю functionToRun через sapply:

> sapply(LETTERS, functionToRun) 
#[1] "hello nested world" 
#[1] "A" 
#Error in get(as.character(match.call()[[1]])) : object 'FUN' not found 

Я могу видеть, что это происходит потому, что фактический вызов при использовании sapply является FUN но FUN не существует в позиции = -1 (по по умолчанию для get). Код, который работает в этой позиции выглядит следующим образом:

get(as.character(match.call()[[1]]),envir = sys.frame(sys.parent()))

Но тот же код не выполняется, если функция не была вызвана через sapply потому sys.frame(sys.parent())) зайдет слишком далеко назад и заканчивается ссылкой на R_GlobalEnv.

Из документации (R 3.2.2) я бы ожидал, что dynGet, возможно, решит проблему только в том случае, если понадобится еще в стеке. Хотя это работает для вызова функции sapply, он не работает, когда функция вызывается сама по себе. (Кроме того, он отмечен как «несколько экспериментальный»). Обратно getAnywhere кажется многообещающим, но, похоже, не работает для функции sapply.

Есть ли надежный способ вернуть функцию, которая в данный момент обрабатывается, т. Е. Работает как для голосовой, так и для сплетенной функции?

То, что я сейчас делаю, - это попытка захвата функции в tryCatch; но я немного сомневаюсь, могу ли я доверять, что get(as.character(match.call()[[1]]),envir = sys.frame(sys.parent())) будет работать во всех случаях упаковки (не просто сочленяется). Итак, я ищу более разумный способ подойти к этой проблеме.

Вопросы потенциально относящиеся:

ответ

1

Я не могу гарантировать, что это будет работать во всех случаях, но это выглядит хорошо:

fun <- function(x) { 
    print(x) 
    y <- exp(x) 
    print(y) 
    sys.function(0) 
} 

fun(1) 
# [1] 1 
# [1] 2.718282 
# function(x) { 
# print(x) 
# y <- exp(x) 
# print(y) 
# sys.function(0) 
# } 
lapply(1:5, fun)[[3]] 
# [1] 1 
# [1] 2.718282 
# [1] 2 
# [1] 7.389056 
# [1] 3 
# [1] 20.08554 
# [1] 4 
# [1] 54.59815 
# [1] 5 
# [1] 148.4132 
# function(x) { 
# print(x) 
# y <- exp(x) 
# print(y) 
# sys.function(0) 
# } 

Конечно, я не понимаю, для чего вам это нужно.

+0

Я думаю, что это довольно общая цель, но я использую это для реализации слоя кеширования, подобного «R.cache». Итак, я хочу получить эту функцию, чтобы я мог ее переварить и использовать в качестве части хэша для хранения результата функции, чтобы гарантировать, что результат кэширования будет соответствовать тому, какой результат будет генерировать функция в настоящее время. – russellpierce