# [R] Evaluating lazily 'f<-' ?

Leonard Mada |eo@m@d@ @end|ng |rom @yon|c@eu
Mon Sep 13 22:18:16 CEST 2021

```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
>> <mailto: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 <mailto: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)
>>>         '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
>>>              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] "This line should be the first printed!"
>>>         [1] "But ERROR: x was already evaluated, which printed
>>>         [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)
>>>         >> '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");};
>>>         >>>> 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
>>>         >>>
>>>         >>> 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 <mailto:R-help using r-project.org> mailing
>>>         list -- To UNSUBSCRIBE and more, see
>>>         https://stat.ethz.ch/mailman/listinfo/r-help
>>>         <https://stat.ethz.ch/mailman/listinfo/r-help>
>>>         PLEASE do read the posting guide
>>>         http://www.R-project.org/posting-guide.html
>>>         <http://www.R-project.org/posting-guide.html>
>>>         and provide commented, minimal, self-contained, reproducible
>>>         code.
>>>

[[alternative HTML version deleted]]

```