From luke at stat.uiowa.edu  Thu Sep 27 13:14:22 2007
From: luke at stat.uiowa.edu (Luke Tierney)
Date: Thu, 27 Sep 2007 06:14:22 -0500 (CDT)
Subject: [Rd] delayedAssign
In-Reply-To: <971536df0709261849s519cb30uf72871bf0f7a8b0d@mail.gmail.com>
References: <971536df0709191230p3a62d94g1dcf8f978dad6305@mail.gmail.com>
	<971536df0709261849s519cb30uf72871bf0f7a8b0d@mail.gmail.com>
Message-ID: <Pine.LNX.4.64.0709270531100.2593@itasca2.wildberry.org>

On Wed, 26 Sep 2007, Gabor Grothendieck wrote:

> I thought that perhaps the behavior in the previous post,
> while inconsistent with the documentation, was not all that
> harmful but I think its related to the following which is a potentially
> serious bug.

The previous discussion already established that as.list of an
environment should not return a list with promises in as promises
should not be visible at the R level.  (Another loophole that needs
closing is $ for environments). So behavior of results that should not
exist is undefined and I cannot see how any such behavior is a further
bug, serious or otherwise.

> z is a list with a single numeric component,
> as the dput output verifies,

Except it isn't, as print or str verify, which might be a problem if z
was an input these functions should expect, but it isn't.

> yet we cannot compare its first element
> to 7 without getting an error message.
>
> Later on we see that its because it thinks that z[[1]] is of type "promise"

As z[[1]] is in fact of type promise that would seem a fairly
reasonable thing to think at this point ...

> and even force(z[[1]]) is of type "promise".

which is consistent with what force is documented to do. The
documentation is quite explicit that force does not do what you seem
to be expecting.  That documentation is from a time when delay()
existed to produce promises at the R level, which was a nightmare
because of all the peculiarities it introduced, which is why it was
removed.

force is intended for one thing only -- replacing code like this:

       # I know the following line look really stupid and you will be
       # tempted to remove it for efficiency but DO NOT: it is needed
       # to make sure that the formal argument y is evaluated at this
       # point.
       y <- y

with this:

      force(y)

which seems much clearer -- at least it suggest you look at the help
page for force to see what it does.

At this point promises should only ever exist in bindings in
environments. If we wanted lazy evaluation constructs more widely
there are really only two sensible options:

     The Scheme option where a special function delay creates a deferred
     evaluation and another, called force in Scheme, forces the evaluation
     but there is no implicit forcing

or

     The Haskell option where data structurs are created lazily so

         z <- list(f(x))

     would create a list with a deferred evaluation, but any attempt to
     access the value of z would force the evaluation. So printing z,
     for example, would force the evaluation but

     	y <- z[[1]]

     would not.

It is easy enough to create a Delay/Force pair that behaves like
Scheme's with the tools available in R if that is what you want.
Haskell, and other fully lazy functional languages, are very
interesting but very different animals from R. For some reason you
seem to be expecting some combination of Scheme and Haskell behavior.

Best,

luke

>
>> f <- function(x) environment()
>> z <- as.list(f(7))
>> dput(z)
> structure(list(x = 7), .Names = "x")
>> z[[1]] == 7
> Error in z[[1]] == 7 :
>  comparison (1) is possible only for atomic and list types
>> force(z[[1]]) == 7
> Error in force(z[[1]]) == 7 :
>  comparison (1) is possible only for atomic and list types
>>
>> typeof(z)
> [1] "list"
>> typeof(z[[1]])
> [1] "promise"
>> typeof(force(z[[1]]))
> [1] "promise"
>> R.version.string # Vista
> [1] "R version 2.6.0 beta (2007-09-23 r42958)"
>
>
> On 9/19/07, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
>> The last two lines of example(delayedAssign) give this:
>>
>>> e <- (function(x, y = 1, z) environment())(1+2, "y", {cat(" HO! "); pi+2})
>>> (le <- as.list(e)) # evaluates the promises
>> $x
>> <promise: 0x032b31f8>
>> $y
>> <promise: 0x032b3230>
>> $z
>> <promise: 0x032b3268>
>>
>> which contrary to the comment appears unevaluated.  Is the comment
>> wrong or is it supposed to return an evaluated result but doesn't?
>>
>>> R.version.string # Vista
>> [1] "R version 2.6.0 alpha (2007-09-06 r42791)"
>>
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

-- 
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:      luke at stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu



[Rd] delayedAssign
Luke Tierney