[Rd] RFC: getifexists() {was [Bug 16065] "exists" ...}

Martin Maechler maechler at stat.math.ethz.ch
Fri Jan 9 14:00:38 CET 2015


>>>>> Michael Lawrence <lawrence.michael at gene.com>
>>>>>     on Thu, 8 Jan 2015 14:02:26 -0800 writes:

    > On Thu, Jan 8, 2015 at 11:57 AM, <luke-tierney at uiowa.edu> wrote:
    >> On Thu, 8 Jan 2015, Michael Lawrence wrote:
    >> 
    >> If we do add an argument to get(), then it should be named consistently
    >>> with the ifnotfound argument of mget(). As mentioned, the possibility of a
    >>> NULL value is problematic. One solution is a sentinel value that indicates
    >>> an unbound value (like R_UnboundValue).
    >>> 
    >> 
    >> A null default is fine -- it's a default; if it isn't right for a
    >> particular case you can provide something else.
    >> 
    >> 
    >>> But another idea (and one pretty similar to John's) is to follow the
    >>> SYMSXP
    >>> design at the C level, where there is a structure that points to the name
    >>> and a value. We already have SYMSXPs at the R level of course (name
    >>> objects) but they do not provide access to the value, which is typically
    >>> R_UnboundValue. But this does not even need to be implemented with SYMSXP.
    >>> The design would allow something like:
    >>> 
    >>> binding <- getBinding("x", env)
    >>> if (hasValue(binding)) {
    >>>   x <- value(binding) # throws an error if none
    >>>   message(name(binding), "has value", x)
    >>> }
    >>> 
    >>> That I think it is a bit verbose but readable and could be made fast. And
    >>> I
    >>> think binding objects would be useful in other ways, as they are
    >>> essentially a "named object". For example, when iterating over an
    >>> environment.
    >>> 
    >> 
    >> This would need a lot more thought. Directly exposing the internals is
    >> definitely not something we want to do as we may well want to change
    >> that design. But there are lots of other corner issues that would have
    >> to be thought through before going forward, such as what happens if an
    >> rm occurs between obtaining a binding object and doing something with
    >> it. Serialization would also need thinking through. This doesn't seem
    >> like a worthwhile place to spend our efforts to me.
    >> 
    >> 

    > Just wanted to be clear that I was not suggesting to expose any internals.
    > We could implement the behavior using SYMSXP, or not. Nor would the binding
    > need to be mutable. The binding would be considered independent of the
    > environment from which it was retrieved. As Pete has mentioned, it could be
    > a useful abstraction to have in general.

It could be, indeed.   Luke's advice (above) and my own gut
feeling do tell me that this is a much larger step than solving
the "getIfExists()" problem.  
In the R development cycle I'd think that it should go to the
next (2015-2016) "3.3" cycle, rather than the current "3.2" one
with goal in April.

    >> Adding getIfExists, or .get, or get0, or whatever seems fine. Adding
    >> an argument to get() with missing giving current behavior may be OK
    >> too. Rewriting exists and get as .Primitives may be sufficient though.

Thank you, Luke.  Given that, Duncan's and the other inputs,
I think we should go for a new function -- .Internal() for now.

To Pete's point about arguments, I did drop 'frame' on purpose 
and indeed we could try to do away with 'where/pos' as well and
have the environment only specified by 'envir'.

Name: I like  get0() for its brevity and prefer it to .get().

Let me expose my current implementation on R-devel ... and start
using it in the 'methods' package so we (Pete H. :-) can start
measuring its impact.

Martin



More information about the R-devel mailing list