From hb at biostat.ucsf.edu  Mon Feb 14 02:19:48 2011
From: hb at biostat.ucsf.edu (Henrik Bengtsson)
Date: Sun, 13 Feb 2011 17:19:48 -0800
Subject: [Rd] Wish: Iterate over any data type/object 'xs' in for (x in xs)
	{ ... }
Message-ID: <AANLkTi=yKaEA4vv-vymcoWHQmgL8+JiCVZUp2h5C7B81@mail.gmail.com>

Hi,

this is about iterating over any data type/object 'xs' in the for-loop
constructor:

  for (x in xs) { ... }

>From help("for"), on can read that 'xs' has to be "An expression
evaluating to a vector (including a list and an expression) or to a
pairlist or NULL. A factor value will be coerced to a character
vector".

If you have a data type/class that contains items that you wish to
iterate over, you could write a as.sequence() method that returns a
vector to iterate over, e.g.

for (x in as.sequence(xs)) {
  print(x);
}

For cases where 'xs' in for (x in xs) { ... } is not a vector (or a
pairlist or NULL), would it be possible to extend R such that it
automatically do the above?

Here is an example based on an S3 class illustrating this:

Letter <- function(i) {
  structure(i, class="Letter");
}

as.character.Letter <- function(x, ...) {
  base::letters[x];
}

print.Letter <- function(x, ...) {
  print(sprintf("Letter: %s", as.character(x)), ...);
}

Letters <- function(n) {
  res <- structure(NA, class="Letters");
  attr(res, "items") <- lapply(1:n, FUN=Letter);
  res;
}

as.sequence.Letters <- function(x, ...) { attr(x, "items"); }
as.sequence <- function(x, ...) UseMethod("as.sequence");


xs <- Letters(5);
for (x in as.sequence(xs)) {
  print(x);
}

[1] "Letter: a"
[1] "Letter: b"
[1] "Letter: c"
[1] "Letter: d"
[1] "Letter: e"


What would be really nice is if one could just do:

for (x in xs) {
  print(x);
}

[1] NA


I'm sure this is way more complicated than I anticipate (e.g. for() is
language construct), but I'd though it's worth throwing it out there.


/Henrik



[Rd] Wish: Iterate over any data type/object 'xs' in for (x in xs) { ... }
Henrik Bengtsson