[R] Evaluating lazily 'f<-' ?

Andrew Simmons @kw@|mmo @end|ng |rom gm@||@com
Mon Sep 13 22:28:55 CEST 2021


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.

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