2015-01-31 5 views
1

У меня есть пример, где я не уверен, что понимаю, что я просматриваю R, и я не думаю, что он делает правильную вещь. Пример модифицируется от «An R и S-PLUS Компаньоне прикладной регрессия» Дж Фоксобъем вложенной функции R

> make.power = function(p) function(x) x^p 
> powers = lapply(1:3, make.power) 
> lapply(powers, function(p) p(2)) 

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

> id = make.power(1) 
> square = make.power(2) 
> cube = make.power(3) 
> id(2) 
[1] 2 
> square(2) 
[1] 4 
> cube(2) 
[1] 8 

Я единственный человек, который нашел это удивительным или тревожным? Есть ли глубокая удовлетворительная причина, почему это так? Спасибо

PS: Я выполнил поиск в Google и SO, но, возможно, из-за общности ключевых слов, связанных с этой проблемой, я вышел с пустыми руками.

PPS: пример мотивирован реальной ошибкой в ​​пакете quickcheck, а не чистым любопытством. У меня есть обходной путь для ошибки, спасибо за вашу заботу. Речь идет об изучении чего-то.

После публикации вопроса, конечно, я получаю представление о другом примере, который мог бы прояснить проблему.

> p = 1 
> id = make.power(p) 
> p = 2 
> square = make.power(p) 
> id(2) 
[1] 4 

p имеет ту же роль, что и переменная цикла, спрятанная в лапке. p передается методом, который в этом случае выглядит как ссылка на make.power. Make.power не оценивает его, просто держит указатель на него. Я на правильном пути?

ответ

2

Это устраняет проблему

make.power = function(p) {force(p); function(x) x^p} 
powers = lapply(1:3, make.power) 
lapply(powers, function(p) p(2)) 

Эта проблема в том, что функция параметры передаются как «обещания», которые не оценены, пока они фактически не используются. Здесь, поскольку вы никогда не используете p при вызове make.power(), он остается во вновь созданной среде как обещание, указывающее на переменную, переданную функции. Когда вы, наконец, позвоните powers(), это обещание наконец-то оценено, и последнее значение p будет с последней итерации lapply. Следовательно, все ваши функции являются кубическими.

force() здесь заставляет оценить обещание. Это позволяет вновь созданной функции иметь другую ссылку на конкретное значение p.

+0

Спасибо. Я готов переключиться на Haskell. – piccolbo

Смежные вопросы