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 at syonic.eu >> <mailto:leo.mada at 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 at r-project.org <mailto:r-help at 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 at r-project.org <mailto:R-help at 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]]
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 at 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 at 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 at 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 at 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]]