2010-10-21 21 views
6

Vorrei creare un vettore di funzioni utilizzando un due agruments funzione 'func', per esempio questa:R: Come creare un vettore di funzioni?

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

ecco come creo il vettore delle funzioni:

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

mio il problema è che tutte le funzioni che compongono il mio vettore sono le stesse, anche se sono state create utilizzando i-through diversi. Sembra che vengano valutati usando l'ultimo valore di i (che è qui una variabile globale).

Qualcuno ha un'idea?

Grazie

+0

Continuo qui come sono un nuovo utente e il forum blocca la mia domanda se contiene troppe righe di codice apparentemente .... – RockScience

+0

Quante linee di codice hai? Aggiungi che è importante per noi rispondere. –

+0

Ho 11 righe di codice ... – RockScience

risposta

3

questo può essere risolto utilizzando un costrutto eval-parse, anche se io consiglio vivamente di non di utilizzare questo costrutto. Spesso provoca più problemi di ogni altra cosa. Ma non sono riuscito a ottenere un modo decente per farlo.

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,")")))) 
} 

La ragione è, come spiegato Aaron: tutto all'interno della definizione di funzione viene preso come è fino a che la valutazione della funzione.

Piccolo commento: questo è soprattutto un elenco di funzioni e non un vettore. È impossibile avere un vettore di tipo "funzione". È anche assolutamente inutile, poiché devi selezionare la funzione usando l'indice [[]] prima di poterlo usare. Quindi aggiungerei l'argomento invece di definire una funzione per ogni possibile valore di uno degli argomenti.

Quindi, ciò che si vuole raggiungere è chiaro, ma se si desidera applicare func con diversi coefficienti, mi chiedo perché non lo fai semplicemente fare:

> 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 

Una variazione sul tema di Marek (evitando il parsing):

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)))) 
} 

il 1L ecc si ottiene, basta indicare sono interi esatte (che occupano meno spazio di memoria).

+1

Invece di 'parse (testo (' cosa migliore usare 'sostituto': 'eval (sostituto (funzione (numero) func (numero = numero, coefficiente = i), lista (i = i)))' – Marek

+1

In ogni caso è lista quindi line in loop può essere modificato in: vector_of_functions [[i]] = eval (sostituto (funzione (numero) func (numero = numero, coefficiente = i), lista (i = i))) –

4

È possibile "allegare" il valore di i a ciascuna funzione ridefinendo i nel proprio ambiente locale (convenientemente creato dalla funzione, local in R). La funzione risultante con i dati "allegati" è chiamata "chiusura".

> 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 
2

Il problema è dovuto alla valutazione pigra, la variabile 'i' è non essere evaluted ad ogni passo, in modo che quando si chiama la funzione utilizza l'ultimo valore. La funzione force è stata creata per forzare la valutazione in casi come questo (c'è un esempio nella pagina di aiuto per? Force che è molto simile alla tua domanda).

Problemi correlati