What you've written will certainly generate an infinite recursion. How could it not?

Specifying an accessor function says to the system "Any reference to this field should be evaluated by calling this function." But then you refer to the field in the function itself, which will result in a call to the function, which ....

Accessor functions are typically used when the field is a proxy for some data stored in a less convenient form (in a C++ object in the case of Rcpp). As a self-contained example:

> ss <- setRefClass("silly", fields = list(now = function(value) {
+ if(missing(value)) Sys.time()
+ else stop("You can't change the time, dummy!")
+ }))
> s1 <- ss$new()
> s1$now
[1] "2010-10-26 08:50:36 PDT"
> s1$now <- "Never"
Error in function (value)  : You can't change the time, dummy!



On 10/26/10 4:57 AM, Jon Clayden wrote:
On 23 October 2010 00:52, Jon Clayden<jon.clay...@gmail.com>  wrote:
On 22 October 2010 18:55, John Chambers<j...@r-project.org>  wrote:

As a suggestion, it would be nice if the accessors() method could be
used to create just "getters" or just "setters" for particular fields,
although I realise this can be worked around by removing the unwanted
methods afterwards.

In other words, read-only fields.  There is a facility for that implemented
already, but it didn't yet make it into the documentation, and it could use
some more testing.  The generator object has a $lock() method that inserts a
write-once type of method for one or more fields.  Example:

fg<- setRefClass("foo", list(bar = "numeric", flag = "character"),
+             methods = list(
+             addToBar = function(incr) {
+                 b = bar + incr
+                 bar<<- b
+                 b
+             }
+             ))
fg$lock("bar")
ff = new("foo", bar = 1.5)
ff$bar<- 2
Error in function (value)  : Field "bar" is read-only

A revision will document this soon.

(And no, the workaround is not to remove methods.  To customize access to a
field, the technique is to write an accessor function for the field that, in
this case, throws an error if it gets an argument.  See the documentation
for the fields argument.  The convention here and the underlying mechanism
are taken from active bindings for environments.)

OK, yes - I see. This is clearly much less superficial than removing
the setter method for a field which can be directly set anyway. I'll
have to try out field accessor functions and get a feel for the
semantics.

Unfortunately, I'm having difficulty working out the accessor function
approach. I've looked in the Rcpp package for examples, but it doesn't
seem to use this feature. If I define

Foo<- setRefClass("Foo", fields=list(bar=function (newBar) {
                                             if (missing(newBar)) bar
                                             else stop("bar is read-only") }),
                           methods=list(barExists=function ()
print(exists("bar"))))

then I can't access the value of "bar" due to infinite recursion.
Using ".self$bar" in the accessor produces the same effect.

f<- Foo$new()
f$barExists()
[1] TRUE
f$bar
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
f$bar()
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?

I can guess why this is happening (accessing "bar" within the accessor
calls itself), but how can I get at the value of "bar" within the
accessor without this occurring?

The other problem is that I can't even set a value at the time of
creation of the object, viz.

f<- Foo$new(bar=2)
Error in function (newBar)  : bar is read-only

Is there a way to test whether "bar" has already been set in the
accessor, so that I can allow it to be set once? (I know lock() allows
this, but it would be useful to be able to replicate the effect using
accessors, so that it can be generalised further where needed.)
Clearly, exists("bar") doesn't do this, as seen above -- presumably
because it sees the method rather than the field, or there is some
default value.

Thanks in advance,
Jon


______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to