1: I think you may have a misunderstanding of the lines()
function. It draws connected lines between a sequence of (x,y)
points. Calling it to draw a single line segment by passing 5 points along the segment doesn't make sense. Here's an example of what lines()
can do:
xlim <- c(0,4); ylim <- c(0,4); plot(NA,xlim=xlim,ylim=ylim,xlab='x',ylab='y');
lines(0:4,c(0,3,4,3,0));

2: To draw separate line segments it is more appropriate to use segments()
. Here's how you can draw your 5 lines using this function:
xlim <- c(1,5); ylim <- c(1,5); plot(NA,xlim=xlim,ylim=ylim,xlab='x',ylab='y');
segments(1:5,1,y1=5);

As you can see, segments()
is vectorized over its coordinate arguments (just as lines()
is), so you can draw multiple lines with a single call. No need for loops.
3: That being said, there are many contexts in graphics production where you have to make multiple calls to graphics functions to produce your desired output. In these cases, I have always used for-loops rather than the *apply()
family. The *apply()
family is mainly useful for data processing when you care about the return value(s) of the lambda call(s) and therefore either capture the result in a variable, or pass it as an argument to another function call. Graphics functions are almost always called purely for their side effect, namely, the drawing of graphics on a graphics device, and thus the return value of the graphics call is discarded. There is unlikely to be a performance benefit from using the *apply()
family, although the analysis is not quite so simple. But any performance benefit you might procure from the *apply()
family can only result from increased efficiency with respect to handling the data produced and returned by the lambda, so it can't apply to graphics calls that don't return data. For example, vapply()
can in some cases provide a noticeable performance benefit, since it can determine in advance exactly what type and size of object will be returned to the caller. Again, that doesn't apply to graphics calls that don't return anything other than NULL
.
4: If you ever find you must call a function that returns data non-invisibly, and you want to prevent it from being displayed in your console, you can manually wrap it in invisible()
. Using your sapply()
call as an example:
sapply(1:5,function(z) lines(y=1:5,x=rep(z,5L)));
## [[1]]
## NULL
##
## [[2]]
## NULL
##
## [[3]]
## NULL
##
## [[4]]
## NULL
##
## [[5]]
## NULL
##
invisible(sapply(1:5,function(z) lines(y=1:5,x=rep(z,5L)))); ## doesn't print anything