On Sat, 12 Mar 2005 [EMAIL PROTECTED] wrote:

Thanks-- Luke Tierney's reply below is very helpful. 'makeActiveBinding' is 
brilliant and I'm pretty sure I can make it do just what I want.

One question though: my first experiment with it was this

makeActiveBinding( 'myAB', function( x) if( missing( x)) get( 'myABguts', 
env=.GlobalEnv) else assign( 'myABguts', x, .GlobalEnv), .GlobalEnv)
exists( 'myAB')

which appeared to return absolutely nothing-- not even a missing or a null. The problem, of course, is that 'myABguts' doesn't exist yet; what seems to happen, though, is that the failure to 'get' causes a *messageless* error inside the active binding function. Is this intended?

What I get is this:

    > makeActiveBinding( 'myAB', function( x)
                                     if( missing( x))
                                         get( 'myABguts', env=.GlobalEnv)
                                     else assign( 'myABguts', x, .GlobalEnv),
                         .GlobalEnv)
    NULL
    Warning message:
    saved workspaces with active bindings may not work properly when loaded ...
    > exists( 'myAB')
    Error in get(x, envir, mode, inherits) : variable "myABguts" was not found

[We might want to get rid of the warning message at this point.]

Currently exists() for active bindings calls the value function even
if mode is "any".  Given that fact and your implementation the message
makes sense to me, and you get the same message if you try to access
the variable:

    > myAB
    Error in get(x, envir, mode, inherits) : variable "myABguts" was not found

You probably should write your function a bit more defensively.

For ordinary bindings that contain promises from delayed evaluation
exists() does not evaluate the promise for mode "any", but does for
other modes of course.  The behavior of exists() for active bindings
is bug.  A quick look at the code suggests that it will be a bit
tricky to fix, so I'm not sure it will get done before 2.1.0.

Best,

luke



I did think that class(env$x) != evalq( class( x), env) was a bit weird, but because it was useful to me, I wan't going to complain. Of course it's entirely true that reliance on the undocumented is dangerous and entirely my liability-- but even ___documented___ features in R have been know to come & go a bit :) . Nowadays I just expect to be buffetted by the winds of change every so often...

Mark

        -----Original Message-----
        From: Luke Tierney [mailto:[EMAIL PROTECTED]
        Sent: Sat 12/03/2005 3:03 PM
        To: Bravington, Mark (CMIS, Hobart)
        Cc: [EMAIL PROTECTED]; r-devel@stat.math.ethz.ch
        Subject: RE: [Rd] delay() has been deprecated for 2.1.0



        On Sat, 12 Mar 2005 [EMAIL PROTECTED] wrote:

        > Uh-oh... I've just written a bunch of code for 'mvbutils' using 'delay', and am 
worried by the statement that "there should be no way to see a <promise:...> object in 
R". At present, it's possible to check whether 'x' is a promise via e.g. 'class( 
.GlobalEnv$x)'. This will be different to 'class( x)' if 'x' is a promise, regardless of whether 
the promise has or has not been forced yet. This can be very useful; my recent code relies on it 
to check whether certain objects have been changed since last being saved. [These certain objects 
are originally assigned as promises to load from individual files. Read-accessing the object keeps 
it as class 'promise', whereas write-access creates a non-promise. Thus I can tell whether the 
individual files need re-saving when the entire workspace is saved.]

        Relying on undocumented features when designing a package is not a
        good idea.  In this case the feature of env$x returning a promise
        contradicts the documentation and is therefore a bug (the
        documentation says that env$x should behave like the corresponding
        get() expression, and that forcec promises and returns their values).

        >
        > The has-it-changed test has been very valuable to me in allowing fast 
handling of large collections of large objects (which is why I've been adding this 
functionality to 'mvbutils'); and apart from is-it-still-a-promise, I can't think 
of any other R-level way of testing whether an object has been modified. [If there 
is another way, please let me know!]
        >
        > Is there any chance of retaining *some* R-level way of checking 
whether an object is a promise, both pre-forcing and post-forcing? (Not 
necessarily via the 'class( env$x)' method, if that's deemed objectionable.)

        This would not be a good idea.  The current behavior of leaving an
        evaluated promise in place is also not a documented feature as far as
        I can see.  It is a convenient way of implementing lazy evaluation in
        an interpreter but it has drawbacks.  One is the cost of the extra
        dereference.  Another is the fact that these promises keep alive their
        environments that might otherwise be inaccessible and hence available
        for GC.  These environments might in turn reference large data
        structures, keeping them alive.  At this point it seems too complicated
        to deal with this in the interpreter, but a compiler might be able to
        prove that a promise can be safely discarded.  (In fact a compiler
        might be able to prove that a promise is not needed in the first
        place).

        There are other possible approaches that you might use, such as active
        bindings (see the help for makeActiveBinding).  If that won't do we
        can look into developing a suitable abstraction that we can implement
        and document in a way that does not tie the hands of the internal
        implementation.

        Best,

        luke

        > Mark Bravington
        > [EMAIL PROTECTED]
        >
        >
        >       -----Original Message-----
        >       From: [EMAIL PROTECTED] on behalf of Duncan Murdoch
        >       Sent: Sat 12/03/2005 3:05 AM
        >       To: r-devel@stat.math.ethz.ch
        >       Cc: Gregory Warnes; David Brahm; Torsten Hothorn; Nagiza F. 
Samatova
        >       Subject: [Rd] delay() has been deprecated for 2.1.0
        >
        >
        >
        >       After a bunch of discussion in the core group, we have decided 
to
        >       deprecate the delay() function (which was introduced as 
"experimental"
        >       in R 0.50).  This is the function that duplicates in R code the
        >       delayed evaluation mechanism (the promise) that's used in 
evaluating
        >       function arguments.
        >
        >       The problem with delay() was that it was handled inconsistently 
(e.g.
        >       sometimes you would see an object displayed as <promise:...>,
        >       sometimes it would be evaluated); it tended to be error-prone 
in usage
        >       (e.g. this was the cause of the bug that makes the curve() 
function
        >       create a "pu" object in the global environment); and it was 
generally
        >       difficult to figure out exactly what the semantics of it should 
be in
        >       order to be consistent.
        >
        >       delay() has been replaced with delayedAssign().  This new 
function
        >       creates a promise and assigns it into an environment.  Once one 
more
        >       set of changes is made and delay() is gone, there should be no 
way to
        >       see a <promise: ...> object in R:  as soon as the object is 
accessed,
        >       it will be evaluated and you'll see the value.
        >
        >       A few packages made use of delay().  I have replaced all of 
those uses
        >       with delayedAssign().  The most common usage was something like 
the QA
        >       code uses:
        >
        >       assign("T", delay(stop("T used instead of TRUE")),
        >                         pos = .CheckExEnv)
        >
        >       This translates to
        >
        >       delayedAssign("T", stop("T used instead of TRUE"), eval.env =
        >       .GlobalEnv, assign.env = .CheckExEnv)
        >
        >       In most cases the "eval.env = .GlobalEnv" argument is not 
necessary
        >       (and in fact it is often a bug, as it was in curve()).  The
        >       environment where the promise is to be evaluated now defaults 
to the
        >       environment where the call is being made, rather than the global
        >       environment, and this is usually what you want.
        >
        >       Package writers who use delay() will now get a warning that it 
has
        >       been deprecated.  They should recode their package to use
        >       delayedAssign instead.
        >
        >       Examples from CRAN of this (I am not sure if this list is 
exhaustive):
        >
        >       exactRankTests, genetics, g.data, maxstat, taskPR, coin
        >
        >       I have cc'd the maintainers of those packages.
        >
        >       If you want a single code base for your package that works in 
both the
        >       upcoming R 2.1.0 and older versions, this presents a problem: 
older
        >       versions don't have delayedAssign.  Here is a workalike 
function that
        >       could be used in older versions:
        >
        >       delayedAssign <- function(x, value,
        >                       eval.env = parent.frame(),
        >                       assign.env = parent.frame()) {
        >        assign(x, .Internal(delay(substitute(value), eval.env)),
        >                  envir = assign.env)
        >       }
        >
        >       Because this function calls the internal delay() function 
directly, it
        >       should work in R 2.1.0+ as well without a warning, but the 
internal
        >       function will eventually go away too, so I don't recommend 
using it in
        >       the long term.
        >
        >       Sorry for any inconvenience that this causes.
        >
        >       Duncan Murdoch
        >
        >       ______________________________________________
        >       R-devel@stat.math.ethz.ch mailing list
        >       https://stat.ethz.ch/mailman/listinfo/r-devel
        >
        > ______________________________________________
        > R-devel@stat.math.ethz.ch 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:      [EMAIL PROTECTED]
        Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu

______________________________________________
R-devel@stat.math.ethz.ch 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: [EMAIL PROTECTED] Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu

______________________________________________
R-devel@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to