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

Henrik Bengtsson henrik.bengtsson at gmail.com
Wed Oct 19 22:25:59 CEST 2016


Thanks Luke.  Yes, this is what I wrote as a workaround in my original
post (and my first follow up):

expr[[2]][1] <- list(x = NULL)
expr[[2]] <- as.pairlist(expr[[2]])

but your

alist <- expr[[2]]
alist[1] <- list(NULL)
expr[[2]] <- as.pairlist(alist)

makes it a bit more clear what the issue is; a pairlist 'x' (here
expr[[2]] and expr) gets coerced to a plain list if one try to do a
`[<-()` assignment.  It would be nice / useful / less surprising /
more consistent(?) if it would remain a pairlist also in those cases.

/Henrik


On Wed, Oct 19, 2016 at 11:47 AM,  <luke-tierney at uiowa.edu> wrote:
> On Wed, 19 Oct 2016, Henrik Bengtsson wrote:
>
>> On Sat, Oct 15, 2016 at 2:00 AM, Martin Maechler
>> <maechler at stat.math.ethz.ch> wrote:
>>>>>>>>
>>>>>>>> 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, thanks for bringing these options up.  Just to make sure no
>> one misreads these comments - I'm not operating on as.list(expr) - it
>> was just used to show the content of the expression.    In my case,
>> I'm operating / modifying expressions and not functions per se, e.g.
>>
>>  expr <- quote(function(x = 1) x)
>>
>> It's not clear to me how I would go about to modify this to be the
>> equivalent of:
>>
>>  expr <- quote(function(x = NULL) x)
>>
>> without having to:
>>
>>  f <- eval(expr)
>>  formals(f) <- list(x=NULL)
>>  expr <- bquote(.(f))
>
>
> You don't need to go through the eval\bquote if you use
>
> expr <- quote(function(x = 1) x)
> alist <- expr[[2]]
> alist[1] <- list(NULL)
> expr[[2]] <- as.pairlist(alist)
>
> Best,
>
> luke
>
>
>>
>> /Henrik
>>
>>>
>>> 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
>>
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>
> --
> Luke Tierney
> 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:   luke-tierney at uiowa.edu
> Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu



More information about the R-devel mailing list