2014-12-30 2 views
8

Об этом коллега спросил меня, и я боролся с этим.Передача выражений кривой() внутри функции

Предположим, я хочу определить функцию, которая принимает выражение (допустим, x^2 для конкретности) в качестве аргумента и передает этот аргумент curve().

Если я хочу сделать это легкий путь, я просто запустить

curve(x^2,from=0,to=3) 

и она отлично работает.

Предположим, что я пытаюсь создать функцию-оболочку (скажем, есть и другие вещи, которые я хочу сделать внутри обертки в дополнение к построения кривой):

f <- function(g) { 
    curve(g,from=0,to=3) 
} 

Это работает, если я прохожу функцию:

f(function(x) x^2) 

он терпит неудачу при попытке передать x^2, когда R пытается вычислить выражение:

f(x^2) 
## Error in eval(expr, envir, enclos) (from #2) : object 'x' not found 

я могу попытаться предотвратить это с помощью substitute в функции:

f0 <- function(g) { 
    str(substitute(g)) 
    curve(substitute(g),from=0,to=3) 
} 
f0(x^2) 
## language x^2 
## Error in curve(substitute(g), from = 0, to = 3) (from #3) : 
## 'expr' must be a function, or a call or an expression containing 'x' 

ОК, который наводит на мысль, может быть, я должен попробовать

f <- function(g) { 
    h <- as.expression(substitute(g)) 
    str(h) 
    curve(as.expression(substitute(g)),from=0,to=3) 
} 
f(x^2) 
## expression(x^2) 
## Error in curve(as.expression(substitute(g)), from = 0, to = 3) (from #4) : 
## 'expr' must be a function, or a call or an expression containing 'x' 

Для чего это стоит,

  • это не удается по-разному с curve(h,...) ("функция h не найдена")
  • он не таким же образом, если as.call() подменяется as.expression()
  • curve() не работает на выражений в любом случае:

curve(expression(x^2),from=0,to=1) 
## Error in curve(expression(x^2), from = 0, to = 1) : 
## 'expr' did not evaluate to an object of length 'n' 

Если я пытаюсь отладки curve(), чтобы увидеть, что происходит, мы имеем:

sexpr <- substitute(expr) 
... 
if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in% 
    all.vars(sexpr))) 
    stop(...) 

Здесь sexpr является substitute(g), который не прошел тест xname %in% all.vars(sexpr) ...

Любые идеи о том, как с этим справиться?

+1

Ты дала 'do.call' выстрел? Похоже, что это может сработать так же, как с помощью 'lm',' glm' и т. Д. –

ответ

6

Я не хотел спрашивать, а затем отвечать, но я выяснил ответ (a?), Немного пошутившись - мне пришло в голову, что я еще не пробовал eval. eval(curve(substitute(g),from=0,to=3)) делает не работы, но это делает:

f1 <- function(g) { 
    eval(substitute(curve(g,from=0,to=3))) 
} 
f1(x^2) 

обновления: @RichardScriven предполагает, что do.call() может работать также - и это делает!

f2 <- function(g) { 
    do.call(curve,list(substitute(g),from=0,to=3)) 
} 
f2(x^2) 

Дальнейшая экспликация приветствуется!

+2

похоже, что эта функция всегда была предназначена для работы в интерактивном режиме (верхний уровень), поэтому обходные пути должны создавать тот же самый вызов, что и вы 'd писать интерактивно, а затем оценивать. – baptiste

+0

Ну, по крайней мере, вы не предложили 'eval (parse (...))' tho ', вы пришли ужасно близко :-). Я согласен с Ричардом С., что 'do.call' является вашим лучшим другом в таких случаях. –