Macro-like for-loops

Peter Dalgaard BSA
02 Oct 1999 20:13:13 +0200

>From the silly-tricks department:

"foreach" <-
function (...) 
    Args <-[-1]
    N <- length(Args)
    Body <- Args[[N]]
    Args <- Args[-N]
    Tags <- names(Args)
    Lists <- lapply(Args, function(a) as.list(a)[-1])
    Lengths <- sapply(Lists, length)
    for ( i in 1:max(Lengths))
        ix <- (i - 1) %% Lengths + 1
        l <- lapply(seq(along=ix), function(j) Lists[[j]][[ix[j]]])
        names(l) <- Tags
        bb <- eval(substitute(substitute(body,l),list(body=Body)))

huey<-rnorm(50); dewey<-rnorm(50); louie<-rnorm(50)

foreach(x=list(huey,dewey,louie), hist(x))

Notice that in contrast to an ordinary for-loop, this kind of loop
automatically gets the titles right on the plots. It is a purely
lexical substitution, equivalent to

hist(huey) ; hist(dewey) ; hist(louie)

In this case, you save -4 keypresses..., but one can easily imagine
the usefulness for eliminating cut+paste errors in more complicated

As written, it is possible to have several list-arguments which are
treated in parallel, recycled to the length of the longest one (as it
was possible to do in good ol' Genstat).

One potential drawback is that (as written, anyway) the function is
playing a bit too many tricks with its arguments. It actually takes
the list expression apart to get at the list of variable names. It
wouldn't work to put an actual list in there, i.e.

l <- list(huey,dewey,louie)
foreach(x=l, hist(x))

cannot work. It obviously never could, because l does not contain the
variable names, but it might be desirable to have some alternate
syntax that worked with stored namelist.

Would it be useful to put something like this in forthcoming versions
of R?

   O__  ---- Peter Dalgaard             Blegdamsvej 3  
  c/ /'_ --- Dept. of Biostatistics     2200 Cph. N   
 (*) \(*) -- University of Copenhagen   Denmark      Ph: (+45) 35327918
~~~~~~~~~~ - (             FAX: (+45) 35327907
r-devel mailing list -- Read
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: