[Rd] How to assign NULL value to pairlist element while keeping it a pairlist?

Martin Maechler maechler at stat.math.ethz.ch
Sat Oct 15 11:00:00 CEST 2016


>>>>> Michael Lawrence <lawrence.michael at gene.com>
>>>>>     on Wed, 12 Oct 2016 15:21:13 -0700 writes:

    > Thanks, this was what I expected. There is a desire to
    > eliminate the usage of pairlist from user code, which
    > suggests the alternative of allowing for function
    > arguments to be stored in lists. That's a much deeper
    > change though.

and I hope we would not go there just for the purpose of
eliminating pairlists from user code, would we ?

As nobody else has mentioned it, I'd really  like to mention the
two (actually 3) functions important for dealing with function
argument lists much more transparently than the
as.list(<function>) things below:

  formals(<f>)
  formals(<f>) <- <arglist>      #  and
  alist()

for creating / modifying function argument lists (which are
pairlists, but the user does not need to know really).
Or did you imply, Henrik, that would you want is not achievable
with these?

Martin

    > On Wed, Oct 12, 2016 at 12:31 PM, Henrik Bengtsson
    > <henrik.bengtsson at gmail.com> wrote:
    >> Michael, thanks for this info.
    >> 
    >> I've stumbled upon this in a case where I walk an R expression (the
    >> AST) and (optionally) modifies it (part of the globals package).  In R
    >> expressions, a function definition uses a pairlist to represent the
    >> arguments.  For example,
    >> 
    >>> expr <- quote(function(x = 1) x)
    >>> str(as.list(expr))
    >> List of 4
    >> $ : symbol function
    >> $ :Dotted pair list of 1
    >> ..$ x: num 1
    >> $ : symbol x
    >> $ :Class 'srcref'  atomic [1:8] 1 15 1 29 15 29 1 1
    >> .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile'
    >> <environment: 0x13918b8>
    >> 
    >> Here the 2nd element is a pairlist:
    >> 
    >>> str(expr[[2]])
    >> Dotted pair list of 1
    >> $ x: num 1
    >>> typeof(expr[[2]])
    >> [1] "pairlist"
    >> 
    >> Now say that I want to update the default value of argument 'x', which
    >> is currently 1, to NULL.  Then I do:
    >> 
    >>> expr[[2]][1] <- list(x = NULL)
    >> 
    >> At this step, I end up with an expression 'expr' where the arguments
    >> are no longer represented by a pairlist:
    >> 
    >>> str(expr[[2]])
    >> List of 1
    >> $ x: NULL
    >>> typeof(expr[[2]])
    >> [1] "list"
    >> 
    >> More importantly, at this point 'expr' no longer holds a valid R expression:
    >> 
    >>> expr
    >> Error: badly formed function expression
    >> 
    >> The solution is to make sure we have a pairlist:
    >> 
    >>> expr[[2]] <- as.pairlist(expr[[2]])
    >>> expr
    >> function(x = NULL) x
    >> 
    >> 
    >> I agree it would be nice to fix this for consistency, but if you bump
    >> into major issues, at least I can live with having to use an explicit
    >> as.pairlist().
    >> 
    >> Thanks
    >> 
    >> Henrik
    >> 
    >> On Wed, Oct 12, 2016 at 10:53 AM, Michael Lawrence
    >> <lawrence.michael at gene.com> wrote:
    >>> Hi Henrik,
    >>> 
    >>> It would help to understand your use case for pairlists.
    >>> 
    >>> Thanks,
    >>> Michael
    >>> 
    >>> On Wed, Oct 12, 2016 at 9:40 AM, Michael Lawrence <michafla at gene.com> wrote:
    >>>> The coercion is probably the most viable workaround for now, as it's
    >>>> consistent with what happens internally for calls. All pairlists/calls
    >>>> are converted to list for subassignment, but only calls are converted
    >>>> back. My guess is that the intent was for users to move from using a
    >>>> pairlist to the "new" (almost 20 years ago) list. In my opinion,
    >>>> consistency trumps "convenience" in this case. If others agree, I'll
    >>>> change it to also coerce back to pairlist.
    >>>> 
    >>>> Michael
    >>>> 
    >>>> On Wed, Oct 12, 2016 at 9:20 AM, Henrik Bengtsson
    >>>> <henrik.bengtsson at gmail.com> wrote:
    >>>>> Hi, I seem to not be able to assign NULL to an element of a pairlist
    >>>>> without causing it to be coerced to a plain list.  For example:
    >>>>> 
>>>>> x <- pairlist(1, 2)
>>>>> class(x)
    >>>>> [1] "pairlist"
    >>>>> 
>>>>> x[1] <- list(NULL)
>>>>> class(x)
    >>>>> [1] "list"
    >>>>> 
    >>>>> This actually true for all [()<- assignments regardless of list value, e.g.
    >>>>> 
>>>>> x <- pairlist(1, 2)
>>>>> x[1] <- list(0)
    >>>>> [1] "list"
    >>>>> 
    >>>>> I also tried assigning a pairlist(), but still the same problem:
    >>>>> 
>>>>> x <- pairlist(1, 2)
>>>>> x[1] <- pairlist(0)
    >>>>> [1] "list"
    >>>>> 
    >>>>> The only workaround I'm aware of is to:
    >>>>> 
    >>>>> x <- as.pairlist(x)
    >>>>> 
    >>>>> at the end.  Any other suggestions?
    >>>>> 
    >>>>> Thanks,
    >>>>> 
    >>>>> Henrik
    >>>>> 
    >>>>> ______________________________________________
    >>>>> R-devel at r-project.org mailing list
    >>>>> https://stat.ethz.ch/mailman/listinfo/r-devel

    > ______________________________________________
    > R-devel at r-project.org mailing list
    > https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list