Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

A recent exchange on the R-sig-teaching list featured a discussion of how best to teach new students R. The initial post included an exercise to write a function, that given a n, will draw n rows of a triangle made up of “*”, noting that for a beginner, this may require two for loops. For example, in pseudo-code:
for i = 1 to n
for j = 1 to i
print "*"


Unfortunately, as several folks (including Richard M. Heiberger and R. Michael Weylandt) noted, for loops in general are not the best way to take full advantage of R. In this entry, we review two solutions they proposed which fit within the R philosophy.

Richard’s solution uses the outer() function to generate a 5×5 matrix of logical values indicating whether the column number is bigger than the row number. Next the ifelse() function is used to replace TRUE with *.
> ifelse(outer(1:5, 1:5, >=), "*", " ")
[,1] [,2] [,3] [,4] [,5]
[1,] "*"  " "  " "  " "  " "
[2,] "*"  "*"  " "  " "  " "
[3,] "*"  "*"  "*"  " "  " "
[4,] "*"  "*"  "*"  "*"  " "
[5,] "*"  "*"  "*"  "*"  "*"


Michael’s solution uses the lapply() function to call a function repeatedly for different values of n. This returns a list rather than a matrix, but accomplishes the same task.
> lapply(1:5, function(x) cat(rep("*", x), "\n"))
*
* *
* * *
* * * *
* * * * *


While this exercise is of little practical value, it does illustrate some important points, and provides a far more efficient as well as elegant way of accomplishing the tasks. For those interested in more, another resource is the R Inferno project of Patric Burns.

SAS
We demonstrate a SAS data step solution mainly to call out some useful features and cautions. In all likelihood a proc iml matrix-based solution would be more elegant;
data test;
array star [5] $star1 - star5; do i = 1 to 5; star[i] = "*"; output; end; run; proc print noobs; var star1 - star5; run; star1 star2 star3 star4 star5 * * * * * * * * * * * * * * *  In particular, note the$ in the array statement, which allows the variables to contain characters; by default variables created by an array statement are numeric. In addition, note the reference to a sequentially suffixed list of variables using the single hyphen shortcut; this would help in generalizing to n rows. Finally, note that we were able to avoid a second do loop (SAS’ primary iterative looping syntax) mainly by luck– the most recently generated value of a variable is saved by default. This can cause trouble, in general, but here it keeps all the previous “*”s when moving on to the next row.