From henrik.bengtsson at gmail.com  Wed Oct 12 21:31:25 2016
From: henrik.bengtsson at gmail.com (Henrik Bengtsson)
Date: Wed, 12 Oct 2016 12:31:25 -0700
Subject: [Rd] How to assign NULL value to pairlist element while keeping
 it a pairlist?
In-Reply-To: <CAOQ5NyfOshFmNp1nQ9Kc7VME2WgqEmJa42Y7m6GRjwsE9=nhTg@mail.gmail.com>
References: <CAFDcVCQEA8Q7Zec6m3mF4PY4mL=VJOihGtXRbKiPq98hKMfY2A@mail.gmail.com>
	<CAOQ5NyeBDy-jAC2-u4TB_CbFtjS4z11dzVuV5_ZmhU11BCwETg@mail.gmail.com>
	<CAOQ5NyfOshFmNp1nQ9Kc7VME2WgqEmJa42Y7m6GRjwsE9=nhTg@mail.gmail.com>
Message-ID: <CAFDcVCQ3bKCE9DqH9XVQYZOWpKxmaOO7u-NnmDjC3FU_b7pFdg@mail.gmail.com>

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



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