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