[R] Evaluating lazily 'f<-' ?

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


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 
> <mailto: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 <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)
>>>>             {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 <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]]



More information about the R-help mailing list