Skip to content

Inf and lazy evaluation

7 messages · James, Bert Gunter, R. Michael Weylandt +2 more

#
Hi,

I have a question involving Inf, lazy evaluation, and maybe argument
recycling.  I have a directory where I am trying to check for the
existence of files of a certain pattern, basically something like
"filename-#", where # is an integer.  I can do something like this,
which works.

file.exists(paste(filename, "-", 1:100, sep = ""))

But I don't like the fact that I am only checking the first 100
possibilities.  What I would prefer is this:

file.exists(paste(filename, "-", 1:Inf, sep = ""))

But that doesn't work, I get the error:

Error in 1:Inf : result would be too long a vector

On one hand, with lazy evaluation, you would think that 1:Inf should
work.  On the other hand, I'm not quite sure what the output would be
if it was working, especially if there were large gaps in the
integers.  Is there a way to get the behavior I seek (i.e. the lazy
evaluation of 1:Inf).

Thanks,


James
#
R is lazy, but not quite that lazy ;-)

It's likely much easier to do this with regexps

something like

list.files()[grepl(paste0(filename, "-"[0123456789]+""), list.files())]

Michael
On Mon, May 14, 2012 at 3:34 PM, J Toll <jctoll at gmail.com> wrote:
#
?list.files


-- Bert
On Mon, May 14, 2012 at 12:34 PM, J Toll <jctoll at gmail.com> wrote:

  
    
#
Thank you all for the replies.

On Mon, May 14, 2012 at 2:45 PM, R. Michael Weylandt
<michael.weylandt at gmail.com> wrote:
Oh, what is this world coming to when you can't count on laziness to
be lazy. ;)  I should probably stop reading about Haskell and their
lazy way of doing things.

As a relatively naive observation, in R, it seems like argument
recycling kind of breaks the power of lazy evaluation.

Thanks for the suggestion of list.files()


James
#
The only place I know lazy evaluation really is visible and widely
used is in the passing of function arguments. It's what allows magic
like

zz <- 1:5
plot(zz)

to know your variable was called "zz." It can also show up in some
places through the promise mechanism, but you have to do a little bit
of work to see them:

zz <- lapply(1:3, function(i) function(x) x^i)

zz[[2]](2)

Without lazy evaluation this would have been 4. Sometimes this winds
up hurting folks -- I'm not sure if it has a "good reason" to be there
or if its a consequence of lazy mechanisms elsewhere (which improve
overall performance)

But I don't believe R allows lazy constructors in any context.

Best,
Michael
On Mon, May 14, 2012 at 4:29 PM, J Toll <jctoll at gmail.com> wrote:
#
Haskell would still have to check  an infinite number of potential files on your hard disk, because it can't now when it's seen everything that fits the naming pattern, now wouldn't it?

Just saying ...
Stefan
#
On May 15, 2012, at 07:25 , R. Michael Weylandt wrote:

            
This is actually *not* lazy evaluation. You could achieve the same effect just by passing the defining expression along with zz. Real lazy evaluation is seen in the arguments to switch() (and "if" once you realize that it is actually a function too) -- only the chosen expression is evaluated. Also, in function definitions, we have default arguments only sometimes evaluated, or not evaluated until some other computation has taken place; e.g., take a look at
function (x, breaks = "Sturges", freq = NULL, probability = !freq, 
    include.lowest = TRUE, right = TRUE, density = NULL, angle = 45, 
    col = NULL, border = NULL, main = paste("Histogram of", xname), 
    xlim = range(breaks), ylim = NULL, xlab = xname, ylab, axes = TRUE, 
    plot = TRUE, labels = FALSE, nclass = NULL, warn.unused = TRUE, 
    ...) 
NULL

and notice that you won't actually ever be setting xlim=range("Sturges"), which would result in an error. What will in fact happen is that you first get the conversion

            breaks <- switch(breaks, sturges = nclass.Sturges(x), 
                `freedman-diaconis` = , fd = nclass.FD(x), scott = nclass.scott(x), 
                stop("unknown 'breaks' algorithm"))

(note, in passing, that lazy evaluation prevents the stop() from kicking in, if a known algorithm is given). Then later on, we have

        breaks <- pretty(range(x), n = breaks, min.n = 1)

so by the time we need the xlim, breaks will be a numeric vector which you _can_ take the range of.