[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