Evaluating lazily 'f<-' ?
Hello Andrew,
On 9/15/2021 6:53 AM, Andrew Simmons wrote:
names(x) <- c("some names")
if different from
`names<-`(x, value = c("some names"))
because the second piece of code does not ever call `<-`. The first
piece of code is (approximately) equivalent to
`*tmp*` <- x
`*tmp*` <- `names<-`(`*tmp*`, value = c("some names"))
x <- `*tmp*`
This is my question: Would there be any negative impact if the code is changed to: x <- 'names<-'(x, value=...); The "x" will be evaluated inside 'names<-' and this function outputs & assigns "x". The "creation" of "x" in the current environment is done only after the call to 'names<-' (if it did not exist before). Leonard
Another example,
y <- `names<-`(x, value = c("some names"))
now y will be equivalent to x if we did
names(x) <- c("some names")
except that the first will not update x, it will still have its old names.
On Mon, Sep 13, 2021 at 4:33 PM Leonard Mada <leo.mada at syonic.eu
<mailto:leo.mada at syonic.eu>> wrote:
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 at syonic.eu
<mailto: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 <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.