[R] Evaluating lazily 'f<-' ?

Leonard Mada |eo@m@d@ @end|ng |rom @yon|c@eu
Mon Sep 13 20:42:56 CEST 2021


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.


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