2

I am noticing this behavior of foreach and print in R. foreach somehow repeats the elements, but assigning result to variable "rectify" it.

> for (i in 1:3) {print(i+1)}
[1] 2
[1] 3
[1] 4
> foreach (i=1:3) %do% {print(i+1)}
[1] 2
[1] 3
[1] 4
[[1]]
[1] 2

[[2]]
[1] 3

[[3]]

[1] 4

> x<-foreach (i=1:3) %do% {print(i+1)}
[1] 2
[1] 3
[1] 4
> x
[[1]]
[1] 2

[[2]]
[1] 3

[[3]]
[1] 4
> foreach (i=1:3, .combine=c) %do% {print(i+1)}
[1] 2
[1] 3
[1] 4
[1] 2 3 4

> foreach (i=1:3) %do% {(i+1)}
[[1]]
[1] 2

[[2]]
[1] 3

[[3]]
[1] 4

> x <-foreach (i=1:3) %do% {(i+1)}
> x
[[1]]
[1] 2

[[2]]
[1] 3

[[3]]
[1] 4

> x<-for (i in 1:3) {(i+1)}
> x
NULL

Moreover, that brings me to the last test with simple for. for loop does not output results while foreach does. If I would want to pick up results from for clause, is there another dedicated way rather than

> x <- NULL
> for (i in 1:3) {x <- cbind(x,(i+1))}
> x
     [,1] [,2] [,3]
[1,]    2    3    4
Kenny
  • 1,902
  • 6
  • 32
  • 61
  • 1
    `foreach` returns a list by default. This is identical behavior to `lapply`. Try `lapply(1:4, print)`. Read the *Value* section of `?foreach` for a discussion. – lmo Oct 06 '17 at 09:36
  • Using `for`, you have to do it manually, since you know the length of a `for` loop prior to running it, pre-allocate the proper object and fill it in. Here, you could do `myVec <- integer(length(1:3))` then `for(i in 1:3) {print(i); myVec[i] <- i}`. Of course, in more complicated iterators, you'll probably have to construct a separate variable that increments from 1 through the length of your loop. – lmo Oct 06 '17 at 09:43
  • Thanks @lmo. That answers the result assignment to variable part. Regarding the fact that what foreach+print seems to be a repetition of results and foreach alone does not, any comments ? – Kenny Oct 06 '17 at 09:45
  • I'm not sure what you mean. You ask the current value to be printed using `print`. The return value of `foreach` is a list and if you don't assign it as you do near the end, it prints to screen. Try my `lapply` example. – lmo Oct 06 '17 at 09:50
  • 1
    That answers my question. Thanks. Got confused between the two set of prints – Kenny Oct 06 '17 at 09:53
  • @lmo. Perhaps you can lend some of your expertise in another question. Thank you. https://stackoverflow.com/questions/46603150/r-function-scope-and-parallelism – Kenny Oct 06 '17 at 10:01

1 Answers1

2

From the help page, ?foreach (emphasis added):

The foreach and %do%/%dopar% operators provide a looping construct that can be viewed as a hybrid of the standard for loop and lapply function. It looks similar to the for loop, and it evaluates an expression, rather than a function (as in lapply), but it's purpose is to return a value (a list, by default), rather than to cause side-effects.

Regarding, the link to lapply, which also returns a list, observe the analog to the above code:

lapply(1:3, print)
[1] 1
[1] 2
[1] 3
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

So the lapply loop prints each value in an iteration and then returns the input as a list in the same manner as foreach.

lmo
  • 37,904
  • 9
  • 56
  • 69