[R] Evaluating lazily 'f<-' ?

Andrew Simmons @kw@|mmo @end|ng |rom gm@||@com
Wed Sep 15 05:53:33 CEST 2021


names(x) <- c("some names")

if different from

`names<-`(x, value = c("some names"))

because the second piece of code does not ever call `<-`. The first piece
of code is (approximately) equivalent to

`*tmp*` <- x
`*tmp*` <- `names<-`(`*tmp*`, value = c("some names"))
x <- `*tmp*`

Another example,

y <- `names<-`(x, value = c("some names"))

now y will be equivalent to x if we did

names(x) <- c("some names")

except that the first will not update x, it will still have its old names.

On Mon, Sep 13, 2021 at 4:33 PM Leonard Mada <leo.mada using syonic.eu> wrote:

>
> On 9/13/2021 11:28 PM, Andrew Simmons wrote:
>
> In the example you gave : r(x) <- 1
> r(x) is never evaluated, the above calls `r<-`,
> in fact r does not even have to be an existing function.
>
>
> I meant:
>
> '*tmp*' <- x; # "x" is evaluated here;
>
> 'r<-' is called after this step, which makes sense in the case of
> subsetting;
>
>
> But I am wondering if changing this behaviour, when NO subsetting is
> performed, would have any impact.
>
> e.g. names(x) = c("some names");
>
> # would it have any impact to skip the evaluation of "x" and call directly:
>
> 'names<-'(x, value);
>
>
> Leonard
>
>
>
> On Mon, Sep 13, 2021, 16:18 Leonard Mada <leo.mada using syonic.eu> wrote:
>
>> Hello,
>>
>>
>> I have found the evaluation: it is described in the section on
>> subsetting. The forced evaluation makes sense for subsetting.
>>
>>
>> On 9/13/2021 9:42 PM, Leonard Mada wrote:
>>
>> Hello Andrew,
>>
>>
>> I try now to understand the evaluation of the expression:
>>
>> e = expression(r(x) <- 1)
>>
>> # parameter named "value" seems to be required;
>> 'r<-' = function(x, value) {print("R");}
>> eval(e, list(x=2))
>> # [1] "R"
>>
>> # both versions work
>> 'r<-' = function(value, x) {print("R");}
>> eval(e, list(x=2))
>> # [1] "R"
>>
>>
>> ### the Expression
>> e[[1]][[1]] # "<-", not "r<-"
>> e[[1]][[2]] # "r(x)"
>>
>>
>> The evaluation of "e" somehow calls "r<-", but evaluates also the
>> argument of r(...). I am still investigating what is actually happening.
>>
>>
>> The forced evaluation is relevant for subsetting, e.g.:
>> expression(r(x)[3] <- 1)
>> expression(r(x)[3] <- 1)[[1]][[2]]
>> # r(x)[3] # the evaluation details are NOT visible in the expression per
>> se;
>> # Note: indeed, it makes sens to first evaluate r(x) and then to perform
>> the subsetting;
>>
>>
>> However, in the case of a non-subsetted expression:
>> r(x) <- 1;
>> It would make sense to evaluate lazily r(x) if no subsetting is involved
>> (more precisely "r<-"(x, value) ).
>>
>> Would this have any impact on the current code?
>>
>>
>> Sincerely,
>>
>>
>> Leonard
>>
>>
>>
>> Sincerely,
>>
>>
>> Leonard
>>
>>
>> On 9/13/2021 9:15 PM, Andrew Simmons wrote:
>>
>> R's parser doesn't work the way you're expecting it to. When doing an
>> assignment like:
>>
>>
>> padding(right(df)) <- 1
>>
>>
>> it is broken into small stages. The guide "R Language Definition" claims
>> that the above would be equivalent to:
>>
>>
>> `<-`(df, `padding<-`(df, value = `right<-`(padding(df), value = 1)))
>>
>>
>> but that is not correct, and you can tell by using `substitute` as you
>> were above. There isn't a way to do what you want with the syntax you
>> provided, you'll have to do something different. You could add a `which`
>> argument to each style function, and maybe put the code for `match.arg` in
>> a separate function:
>>
>>
>> match.which <- function (which)
>> match.arg(which, c("bottom", "left", "top", "right"), several.ok = TRUE)
>>
>>
>> padding <- function (x, which)
>> {
>>     which <- match.which(which)
>>     # more code
>> }
>>
>>
>> border <- function (x, which)
>> {
>>     which <- match.which(which)
>>     # more code
>> }
>>
>>
>> some_other_style <- function (x, which)
>> {
>>     which <- match.which(which)
>>     # more code
>> }
>>
>>
>> I hope this helps.
>>
>> On Mon, Sep 13, 2021 at 12:17 PM Leonard Mada <leo.mada using syonic.eu> wrote:
>>
>>> Hello Andrew,
>>>
>>>
>>> this could work. I will think about it.
>>>
>>> But I was thinking more generically. Suppose we have a series of
>>> functions:
>>> padding(), border(), some_other_style();
>>> Each of these functions has the parameter "right" (or the group of
>>> parameters c("right", ...)).
>>>
>>>
>>> Then I could design a function right(FUN) that assigns the value to this
>>> parameter and evaluates the function FUN().
>>>
>>>
>>> There are a few ways to do this:
>>> 1.) Other parameters as ...
>>> right(FUN, value, ...) = value; and then pass "..." to FUN.
>>> right(value, FUN, ...) = value; # or is this the syntax? (TODO: explore)
>>>
>>> 2.) Another way:
>>> right(FUN(...other parameters already specified...)) = value;
>>> I wanted to explore this 2nd option: but avoid evaluating FUN, unless
>>> the parameter "right" is injected into the call.
>>>
>>> 3.) Option 3:
>>> The option you mentioned.
>>>
>>>
>>> Independent of the method: there are still weird/unexplained behaviours
>>> when I try the initial code (see the latest mail with the improved code).
>>>
>>>
>>> Sincerely,
>>>
>>>
>>> Leonard
>>>
>>>
>>> On 9/13/2021 6:45 PM, Andrew Simmons wrote:
>>>
>>> I think you're trying to do something like:
>>>
>>> `padding<-` <- function (x, which, value)
>>> {
>>>     which <- match.arg(which, c("bottom", "left", "top", "right"),
>>> several.ok = TRUE)
>>>     # code to pad to each side here
>>> }
>>>
>>> Then you could use it like
>>>
>>> df <- data.frame(x=1:5, y = sample(1:5, 5))
>>> padding(df, "right") <- 1
>>>
>>> Does that work as expected for you?
>>>
>>> On Mon, Sep 13, 2021, 11:28 Leonard Mada via R-help <
>>> r-help using r-project.org> wrote:
>>>
>>>> I try to clarify the code:
>>>>
>>>>
>>>> ###
>>>> right = function(x, val) {print("Right");};
>>>> padding = function(x, right, left, top, bottom) {print("Padding");};
>>>> 'padding<-' = function(x, ...) {print("Padding = ");};
>>>> df = data.frame(x=1:5, y = sample(1:5, 5)); # anything
>>>>
>>>> ### Does NOT work as expected
>>>> 'right<-' = function(x, value) {
>>>>      print("This line should be the first printed!")
>>>>      print("But ERROR: x was already evaluated, which printed
>>>> \"Padding\"");
>>>>      x = substitute(x); # x was already evaluated before substitute();
>>>>      return("Nothing"); # do not now what the behaviour should be?
>>>> }
>>>>
>>>> right(padding(df)) = 1;
>>>>
>>>> ### Output:
>>>>
>>>> [1] "Padding"
>>>> [1] "This line should be the first printed!"
>>>> [1] "But ERROR: x was already evaluated, which printed \"Padding\""
>>>> [1] "Padding = " # How did this happen ???
>>>>
>>>>
>>>> ### Problems:
>>>>
>>>> 1.) substitute(x): did not capture the expression;
>>>> - the first parameter of 'right<-' was already evaluated, which is not
>>>> the case with '%f%';
>>>> Can I avoid evaluating this parameter?
>>>> How can I avoid to evaluate it and capture the expression: "right(...)"?
>>>>
>>>>
>>>> 2.) Unexpected
>>>> 'padding<-' was also called!
>>>> I did not know this. Is it feature or bug?
>>>> R 4.0.4
>>>>
>>>>
>>>> Sincerely,
>>>>
>>>>
>>>> Leonard
>>>>
>>>>
>>>> On 9/13/2021 4:45 PM, Duncan Murdoch wrote:
>>>> > On 13/09/2021 9:38 a.m., Leonard Mada wrote:
>>>> >> Hello,
>>>> >>
>>>> >>
>>>> >> I can include code for "padding<-"as well, but the error is before
>>>> that,
>>>> >> namely in 'right<-':
>>>> >>
>>>> >> right = function(x, val) {print("Right");};
>>>> >> # more options:
>>>> >> padding = function(x, right, left, top, bottom) {print("Padding");};
>>>> >> 'padding<-' = function(x, ...) {print("Padding = ");};
>>>> >> df = data.frame(x=1:5, y = sample(1:5, 5));
>>>> >>
>>>> >>
>>>> >> ### Does NOT work
>>>> >> 'right<-' = function(x, val) {
>>>> >>         print("Already evaluated and also does not use 'val'");
>>>> >>         x = substitute(x); # x was evaluated before
>>>> >> }
>>>> >>
>>>> >> right(padding(df)) = 1;
>>>> >
>>>> > It "works" (i.e. doesn't generate an error) for me, when I correct
>>>> > your typo:  the second argument to `right<-` should be `value`, not
>>>> > `val`.
>>>> >
>>>> > I'm still not clear whether it does what you want with that fix,
>>>> > because I don't really understand what you want.
>>>> >
>>>> > Duncan Murdoch
>>>> >
>>>> >>
>>>> >>
>>>> >> I want to capture the assignment event inside "right<-" and then call
>>>> >> the function padding() properly.
>>>> >>
>>>> >> I haven't thought yet if I should use:
>>>> >>
>>>> >> padding(x, right, left, ... other parameters);
>>>> >>
>>>> >> or
>>>> >>
>>>> >> padding(x, parameter) <- value;
>>>> >>
>>>> >>
>>>> >> It also depends if I can properly capture the unevaluated expression
>>>> >> inside "right<-":
>>>> >>
>>>> >> 'right<-' = function(x, val) {
>>>> >>
>>>> >> # x is automatically evaluated when using 'f<-'!
>>>> >>
>>>> >> # but not when implementing as '%f%' = function(x, y);
>>>> >>
>>>> >> }
>>>> >>
>>>> >>
>>>> >> Many thanks,
>>>> >>
>>>> >>
>>>> >> Leonard
>>>> >>
>>>> >>
>>>> >> On 9/13/2021 4:11 PM, Duncan Murdoch wrote:
>>>> >>> On 12/09/2021 10:33 a.m., Leonard Mada via R-help wrote:
>>>> >>>> How can I avoid evaluation?
>>>> >>>>
>>>> >>>> right = function(x, val) {print("Right");};
>>>> >>>> padding = function(x) {print("Padding");};
>>>> >>>> df = data.frame(x=1:5, y = sample(1:5, 5));
>>>> >>>>
>>>> >>>> ### OK
>>>> >>>> '%=%' = function(x, val) {
>>>> >>>>        x = substitute(x);
>>>> >>>> }
>>>> >>>> right(padding(df)) %=% 1; # but ugly
>>>> >>>>
>>>> >>>> ### Does NOT work
>>>> >>>> 'right<-' = function(x, val) {
>>>> >>>>        print("Already evaluated and also does not use 'val'");
>>>> >>>>        x = substitute(x); # is evaluated before
>>>> >>>> }
>>>> >>>>
>>>> >>>> right(padding(df)) = 1
>>>> >>>
>>>> >>> That doesn't make sense.  You don't have a `padding<-` function, and
>>>> >>> yet you are trying to call right<- to assign something to
>>>> padding(df).
>>>> >>>
>>>> >>> I'm not sure about your real intention, but assignment functions by
>>>> >>> their nature need to evaluate the thing they are assigning to, since
>>>> >>> they are designed to modify objects, not create new ones.
>>>> >>>
>>>> >>> To create a new object, just use regular assignment.
>>>> >>>
>>>> >>> Duncan Murdoch
>>>> >
>>>>
>>>> ______________________________________________
>>>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>>> PLEASE do read the posting guide
>>>> http://www.R-project.org/posting-guide.html
>>>> and provide commented, minimal, self-contained, reproducible code.
>>>>
>>>

	[[alternative HTML version deleted]]



More information about the R-help mailing list