2013-04-16 13 views
14

Esiste un costrutto di pacchetto o linguaggio in R che facilita o fornisce l'implementazione di "Python-like generators"?Funzioni del generatore in R

per "generatori Python-like" intendo funzioni che mantengono lo stato tra chiamate, nella sintassi R ed ai prestiti parola resa da Python sarà simile:

iterable.fun <- function(){ 
    yield list('a','b','c') 
} 

Con resa anziché un ritorno, quindi chiamando la funzione per tre volte consecutive darebbe:

> iterable.fun() 
    'a' 
> iterable.fun() 
    'b' 
> iterable.fun() 
    'c' 

Edit: ho lasciato fuori un AS pect di generatori Python che li rende diversi dagli iteratori. È che l'intera lista di oggetti da iterare non è costruita sulla prima chiamata e quindi iterata, ma ogni chiamata di funzione crea l'unico elemento che ritornerà per quella chiamata.

+1

R cerca di essere un linguaggio funzionale. Questa richiesta può essere soddisfatta solo da un approccio non funzionale. Puoi sovvertire la funzionalità con '<< -' se necessario, ma probabilmente è meglio pensare a ciò che vuoi come risultato finale e trovare una soluzione funzionale. –

+0

Domanda simile: http://stackoverflow.com/questions/23509381/lazy-sequences-in-r – cbare

+0

Inoltre, Luke Tierney ha scritto una [Lazy List Implementation] (http://homepage.cs.uiowa.edu/~ luke/R/artificiale/lazy.pdf). – cbare

risposta

15

Il pacchetto iterators ha questa funzionalità

library(iterators) 
abc <- iter(c('a','b','c')) 
nextElem(abc) 
## [1] "a" 
nextElem(abc) 
## [1] "b" 
nextElem(abc) 
## [1] "c" 

Oppure si potrebbe usare lambda.r e <<-. Questo esempio è stato modificato dalla

http://cartesianfaith.wordpress.com/2013/01/05/infinite-generators-in-r/

ci sono altri esempi nel post del blog

library(lambda.r) 
seq.gen(start) %as% { 
    value <- start - 1L 
    function() { 
    value <<- value + 1L 
    return(value) 
    } 
} 



foo <- seq.gen(1) 
foo() 
## [1] 1 
foo() 
## [1] 2 
foo() 
## [1] 3 

nota che si potrebbe anche usare una normale funzione per fare questo.

seq.gen <-function(start) { 
    value <- start - 1L 
    function() { 
    value <<- value + 1L 
    return(value) 
    } 
} 
foo2 <- seq.gen(1) 
foo2() 
## [1] 1 
foo2() 
## [1] 2 
foo2() 
## [1] 3 

Se si desidera selezionare da un possibile lista, allora si potrebbe forse farlo utilizzando switch

seq.char(start) %as% { 
    value <- start - 1L 
    function() { 
    value <<- value + 1L 
    return(switch(value,'a','b','c')) 
    } 
} 

foo.char <- seq.char(1) 
foo.char() 
## [1] "a" 
foo.char() 
## [1] "b" 
foo.char() 
## [1] "c" 
+0

Grazie per la tua risposta, sfortunatamente un iteratore non è quello di cui stavo parlando e penso di non averlo chiarito per chi non ha familiarità con le funzioni del generatore Python. – papirrin

+0

@papirrin - guarda la mia modifica. – mnel

+0

Nice edit, risponde anche alle domande che non ho fatto. – papirrin