Skip to content

delayedAssign

8 messages · Peter Dalgaard, Gabor Grothendieck, Luke Tierney

#
The last two lines of example(delayedAssign) give this:
$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?
[1] "R version 2.6.0 alpha (2007-09-06 r42791)"
#
Gabor Grothendieck wrote:
My guess would be that the behaviour is unintended. It should be harder 
than that to get promises visible at the user level. Luke?

  
    
#
Also note that earlier in the same example we have:
[1] "new!"
x
[1] "R version 2.6.0 alpha (2007-09-06 r42791)"

That is substitute(x) gives x, not msg.
On 9/19/07, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
7 days later
#
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.  z is a list with a single numeric component,
as the dput output verifies, 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"
and even force(z[[1]]) is of type "promise".
structure(list(x = 7), .Names = "x")
Error in z[[1]] == 7 :
  comparison (1) is possible only for atomic and list types
Error in force(z[[1]]) == 7 :
  comparison (1) is possible only for atomic and list types
[1] "list"
[1] "promise"
[1] "promise"
[1] "R version 2.6.0 beta (2007-09-23 r42958)"
On 9/19/07, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
#
On Wed, 26 Sep 2007, Gabor Grothendieck wrote:

            
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.
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.
As z[[1]] is in fact of type promise that would seem a fairly
reasonable thing to think at this point ...
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

  
    
#
Thanks for the explanation.

For lists either: (a) promises should be evaluated as they
enter the list or (b) promises evaluated as they exit the
list (i.e. as they are compared, inspected, etc.).  I gather
the intent was (a) but it does not happen that way due to
a bug in R.   Originally I thought (b) would then occur but
my surprise was that it does not occur either which is why
I feel its more serious than I had originally thought.

I think its ok if promises only exist in environments and not
lists.  Items that would be on my wishlist would be to be able
to do at R level the two mentioned previously

https://stat.ethz.ch/pipermail/r-devel/2007-September/046943.html

and thirdly an ability to get the evaluation environment, not just the
expression,
associated with a promise -- substitute only gets the expression.
Originally I thought I would need some or all of these wish items
and then thought not but am back to the original situation again as I use
them more and realize that they are at least important
for debugging (its very difficult to debug situations involving promises as
there is no way to inspect the evaluation environment so you are never sure
which environment a given promise is evaluating in) and possibly
for writing programs as well.
On 9/27/07, Luke Tierney <luke at stat.uiowa.edu> wrote:
#
On Thu, 27 Sep 2007, Gabor Grothendieck wrote:

            
What makes you conclude that this is what "should" happen?

Again, promises are internal.  We could, and maybe will, eliminate
promises in favor of a mark on bindings in environments that indicates
that they need to be evaluated.  At the R level this woud produce the
same behavior as we currently (intend to) have.

If we allowed lazy structures outside of bindings then I still don't
see how (b) "should" happen.  With Scheme-like semantics we would
definitely NOT want this to happen; with Haskell-like semantics any
attempt to look at the value (including priting) would result in
evaluation (and replacing the promise/thunk/whatever by its value).
I am still not persuaded that tools for inspecting environments are
worth the time and effort required but I am prepared to be.

Best,

luke

  
    
#
You or Peter stated that promises are internal so clearly they
should be evaluated going in or out of lists.  Otherwise you get
the current situation.

If you had just wasted as much time as I have trying to debug
a program with promises you would immediately understand why
it was necessary
to be able to query a promise for its evaluation environment.  I think
this is an obvious requirement for anyone dealing with promises since
you are never quite sure what environment the promises are being
evaluated with respect to.  If you knew this then you would immediately
understand if its doing what you think.  Its like trying to debug a program
without any way of finding out what the variables are at any point in the
program.

For the other features see #1 in these release notes (for the
next version of proto) which features lazy evaluation:

http://r-proto.googlecode.com/svn/trunk/inst/ReleaseNotes.txt

The examples there already seem to work with the devel version of proto
(available on the Source tab of r-proto.googlecode.com) but
not necessarily in a desirable way.  In the current implementation cloned
objects have their promises forced in the specified environment
defaulting to current environment rather than the original environment.
We don't know what the
original environment is since its not available at the R level, i.e.
substitute will tell us the expression but not the evaluation environment.
We could redundantly pass the evaluation environment around but then
it would not
be garbage collected causing large amount of inefficiency and
anyways, it seems pointless when the information is there and
just needs to be made accessible.  I think the default is that cloned
promises should be evaluated in the original
environment since that one is known to hold the variables that are
being evaluated whereas the current environment may or may not have
variables of those names.  In order to try this and variations on this
we need the three wish list items.
On 9/27/07, Luke Tierney <luke at stat.uiowa.edu> wrote: