[R] Evaluating lazily 'f<-' ?

Bert Gunter bgunter@4567 @end|ng |rom gm@||@com
Mon Sep 13 22:09:47 CEST 2021


e = expression(r(x) <- 1)

lapply(e, as.list)
[[1]]
[[1]][[1]]
`<-`

[[1]][[2]]
r(x)

[[1]][[3]]
[1] 1
#######################

lapply(e[[1]], as.list)
[[1]]
[[1]][[1]]
`<-`


[[2]]
[[2]][[1]]
r

[[2]][[2]]
x


[[3]]
[[3]][[1]]
[1] 1

However, I would urge you not to go down this rabbit hole unless you
are comfortable with recursion and have good reason to compute on the
language.

Bert Gunter

"The trouble with having an open mind is that people keep coming along
and sticking things into it."
-- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )

On Mon, Sep 13, 2021 at 11:43 AM Leonard Mada via R-help
<r-help using r-project.org> 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.
>
>
> 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]]
>
> ______________________________________________
> 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.



More information about the R-help mailing list