[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