Р: Как создать вектор функций? - PullRequest
6 голосов
/ 21 октября 2010

Я хотел бы создать вектор функций, используя функцию двух операторов 'func', например, такую:

func = function(number, coefficient) {  
    return(coefficient*number)  
}

вот как я создаю вектор функций:

vector_of_functions = NULL  
for (i in 1:4) {  
vector_of_functions = c(vector_of_functions,
    function(number) func(number=number, coefficient=i))  
}

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

У кого-нибудь есть идея?

Спасибо

Ответы [ 3 ]

4 голосов
/ 21 октября 2010

Вы можете «прикрепить» значение i к каждой функции, переопределив i в ее собственной локальной среде (удобно создаваемой функцией, local в R). Результирующая функция с данными «attach» называется «замыканием».

> vector_of_functions = NULL  
> for (i in 1:4) {  
+ vector_of_functions = c(vector_of_functions,
+     local({i <- i;function(number) func(number=number, coefficient=i)}))
+ }
> vector_of_functions[[1]](1)
[1] 1
> vector_of_functions[[2]](1)
[1] 2
> vector_of_functions[[3]](1)
[1] 3
> vector_of_functions[[4]](1)
[1] 4
3 голосов
/ 21 октября 2010

Эту проблему можно решить с помощью конструкции eval-parse, хотя я настоятельно советую вам не использовать эту конструкцию. Это часто вызывает больше проблем, чем что-либо еще. Но я не мог найти приличный способ сделать это.

vector_of_functions = NULL
for (i in 1:4) {
vector_of_functions = c(vector_of_functions,
  eval(parse(text=paste("function(number) func(number=number, coefficient=",i,")"))))
}

Причина, как объяснил Аарон: все в определении функции принимается как есть до оценки функции.

Небольшое замечание: это особенно список функций , а не вектор. Невозможно иметь вектор типа «функция». Это также абсолютно бесполезно, так как вы должны выбрать функцию, используя индекс [[]], прежде чем сможете ее использовать. Тогда я бы просто добавил аргумент вместо определения функции для каждого возможного значения одного из аргументов.

То, чего вы хотите достичь, неясно, но если вы хотите применить func с разными коэффициентами, я удивляюсь, почему вы просто не делаете:

> x <- c(10,20,30)
> sapply(1:4,function(y)func(number=x,coefficient=y))
     [,1] [,2] [,3] [,4]
[1,]   10   20   30   40
[2,]   20   40   60   80
[3,]   30   60   90  120

Вариация на тему Марека (избегая разбора):

vector_of_functions = NULL
for (i in 1:4) {
vector_of_functions = c(vector_of_functions,
  eval(substitute(function(number) func(number=number, coefficient=i),list(i=i))))
}

1L и т. Д., Которые вы получаете, просто указывают, что они являются точными целыми числами (которые занимают меньше места в памяти).

2 голосов
/ 21 октября 2010

Проблема связана с отложенной оценкой, переменная 'i' не оценивается на каждом шаге, поэтому при вызове функции используется последнее значение. Функция force была создана для принудительной оценки в подобных случаях (на странице справки приведен пример? Force, очень похожий на ваш вопрос).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...