Re: [R] How to change the value of a class slot
On Wed, 2005-06-08 at 14:15 +0200, Thomas Petzoldt wrote: ... Hello Ross, I see that your question was related to S4, but I just noticed a solution based on the R.oo package so I thought I would add a solution based on the proto package too. We had similar problems several times ago and (to my surprise) found R to be an extremely flexible language even for these things. Our favorite solution is available as package(proto). It requires R 2.1, because of several subtle improvements regarding environments, which made our implementation more streamlined. Does the following example do what you intended? Certainly looks like it. It seems R has an embarrassment of object systems. R.oo, which someone else mentioned, also has the semantics I was thinking of. There's an interesting paper here http://www.ci.tuwien.ac.at/Conferences/DSC-2003/Proceedings/Bengtsson.pdf which contrasts what I was looking for, which it calls class-object-oriented programming (COOP) with what R does, which it calls functional-object-oriented programming (FOOP). The paper also notes that call-by-value vs call-by-reference, which is the root of the slot update problem, is really orthogonal to the FOOP/COOP distinction. It's easy to imagine FOOP with call-by-reference. R.oo uses references. That paper also mentions that Omegahat has on OOP package, which apparently is similar in spirit to R.oo while taking a more low-level approach to the implementation. Ross ##= library(proto) ## 1) define an object CompletePathMaker - proto( index = 0, bumpIndex = function(., dindex = 1) .$index - .$index + as.integer(dindex) ) ## 2) create a child object of CompletePathMaker cpm - CompletePathMaker$proto() ## 3) set the index component to 3 cpm$index - 3 ## 4) iterate the index cpm$bumpIndex(2) ## print the result cpm$index ##= __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
On Wed, 2005-06-08 at 09:13 +0200, Uwe Ligges wrote: [extensive deletions. Discussion concerned my desire to have a function change the value of an object in a way that had effects outside of the function, without returning the object.] You have to think about scoping rules and it will be clear that the approach you are expecting is not a clean one in S. Could you say a bit more about that? I meant the following simple example (not related to any object oriented programming from the S point of view, but maybe well from your point of view?): Say you want a function foo() that simply incements the argument: a - 1 foo(a) a # now is 2 But what happens if there is (more than) one a (in different environments), but no a in the environment foo(a) is called from. Which a do you want to change in this case? Seems to be rather dangerous. Uwe Ligges I believe your example assumes that foo is updating the outer a by cheating and directly modifying enclosing environments. (I figure it also needs to get the name of its actual argument to do this, which would also involve slightly dirty tricks.) This does seem to be the only way to do it in standard R. In contrast, I wanted something like foo-function(formalArg){ formalArg - new value return something else } so that if I call foo(a), a has the new value after the call. Unfortunately for me, that doesn't work. Call-by-value semantics imply that it can't. __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Ross Boylan wrote: I believe your example assumes that foo is updating the outer a by cheating and directly modifying enclosing environments. (I figure it also needs to get the name of its actual argument to do this, which would also involve slightly dirty tricks.) This does seem to be the only way to do it in standard R. In contrast, I wanted something like foo-function(formalArg){ formalArg - new value return something else } so that if I call foo(a), a has the new value after the call. Unfortunately for me, that doesn't work. Call-by-value semantics imply that it can't. What about call by reference like this: library(proto) arg - proto(x=1) foo-function(formalArg){ formalArg$x - formalArg$x + 1.23 #return something else } foo(arg) arg$x [1] 2.23 Best regards Thomas P. __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
On 6/9/2005 3:04 PM, Ross Boylan wrote: On Wed, 2005-06-08 at 09:13 +0200, Uwe Ligges wrote: [extensive deletions. Discussion concerned my desire to have a function change the value of an object in a way that had effects outside of the function, without returning the object.] You have to think about scoping rules and it will be clear that the approach you are expecting is not a clean one in S. Could you say a bit more about that? I meant the following simple example (not related to any object oriented programming from the S point of view, but maybe well from your point of view?): Say you want a function foo() that simply incements the argument: a - 1 foo(a) a # now is 2 But what happens if there is (more than) one a (in different environments), but no a in the environment foo(a) is called from. Which a do you want to change in this case? Seems to be rather dangerous. Uwe Ligges I believe your example assumes that foo is updating the outer a by cheating and directly modifying enclosing environments. (I figure it also needs to get the name of its actual argument to do this, which would also involve slightly dirty tricks.) This does seem to be the only way to do it in standard R. In contrast, I wanted something like foo-function(formalArg){ formalArg - new value return something else } so that if I call foo(a), a has the new value after the call. Unfortunately for me, that doesn't work. Call-by-value semantics imply that it can't. Here are some dirty ways to do it: foo - function(FormalArg, value) { + assign(as.character(substitute(FormalArg)), value, envir=sys.frame(sys.parent())) + } x Error: Object x not found foo(x, 4) x [1] 4 That one does the assignment in the caller's frame, not necessarily the place that FormalArg was found. If you want to change a value that you know exists, you could do something like this: which.env - function(name, envir = sys.frame(sys.parent())) { if (!exists(name, envir)) stop('not found') result - envir while (!is.null(result) !exists(name, result, inherits = FALSE)) result - parent.env(result) return(result) } foo - function(FormalArg, value) { name - as.character(substitute(FormalArg)) assign(name, value, which.env(name, sys.frame(sys.parent( } Duncan Murdoch __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Ross Boylan wrote: The paper also notes that call-by-value vs call-by-reference, which is the root of the slot update problem, is really orthogonal to the FOOP/COOP distinction. It's easy to imagine FOOP with call-by-reference. R.oo uses references. Yes, it can be found on http://www.maths.lth.se/help/R/R.oo/ That paper also mentions that Omegahat has on OOP package, which apparently is similar in spirit to R.oo while taking a more low-level approach to the implementation. Ross The Omegahat related article was in R News: Object-Oriented Programming in R by John M. Chambers Duncan Temple Lang. R News Vol. 1/3, September 2001, p 17. http://cran.r-project.org/doc/Rnews/Rnews_2001-3.pdf Thomas __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Ross Boylan wrote: On Tue, 2005-06-07 at 08:36 +0200, Uwe Ligges wrote: Ross Boylan wrote: On Sat, Jun 04, 2005 at 07:08:56PM +0200, Martin Maechler wrote: Ross nextPath - function(pm){ #pm is a CompletePathMaker Ross[EMAIL PROTECTED] - [EMAIL PROTECTED](1) Ross [etc] If your nextPath function has 'pm' as its last statement it will return the updated object, and if you call it as mypm - nextPath(mypm) you are 1) updating mypm 2) in a proper S way (i.e. no cheating). Regards, Martin Wow. This is almost the exact inverse of the usual object behavior, in which only the class itself can update the slots (aka instance variables). None of the methods of the class can update instances of the class persistently without the help of outsiders, and only outsiders can change the slot values. (Yes, I realize that using the idiom you suggest of returning a new object one can have only class methods actually fiddling with the slots.) The inability of a class method to change a class object without outside help seems unfortunate. It looks as if instances of class objects are best thought of as immutable once created. Obviously, there are many definition of object oriented programming, and yours seems to be different from the S4 definition. Yes. And though there are many definitions of object oriented (at least, many implementations), I'd say the minimum requirement to be object oriented is to have objects that encapsulate both state (instance variables/slots) and behavior (methods). S4 objects do not fully encapsulate state because they require outside assistance to alter the state of the object (with the exception of assignment operators). The smalltalker in me also gets nervous that code outside the class can access the slots, but there are many object systems that act that way. The way in which names of methods of unrelated classes interfere with each other seems a break-down of the encapsulation of behavior, though the problem strictly is not with the behavior but just with the name. To return to the concrete problem that got me started, if class Specification defines a method likelihood taking as arguments instances of class Specification, Path and Parameters, then it is awkward to define a method likelihood for the class Model when that method has arguments of class Model, Specification, data.frame, and vector, particularly if different names for the formal arguments are desired. (I think technically it could be done, but only in a very ugly way--i.e., better to use different method names for the two classes). I was going to answer your first question at first, but you have not given enough details - in particular it was not clear to me why your approach did not work. I assumed that you are assigning the new object again, which is the S way. I wasn't, which is why it didn't work. I wanted the function to return some other value than the object it was operating on. You have to think about scoping rules and it will be clear that the approach you are expecting is not a clean one in S. Could you say a bit more about that? I meant the following simple example (not related to any object oriented programming from the S point of view, but maybe well from your point of view?): Say you want a function foo() that simply incements the argument: a - 1 foo(a) a # now is 2 But what happens if there is (more than) one a (in different environments), but no a in the environment foo(a) is called from. Which a do you want to change in this case? Seems to be rather dangerous. Uwe Ligges I had thought of the issue more in terms of function calls in S being call by value, preventing updates to the original arguments. So the issue isn't so much the scope of the names of function arguments (that scope being limited to the function body), but the properties of the thing they refer to (conceptually, a copy of the argument, not the original). __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Ross Boylan wrote: I defined an S4 class with a slot i. Then I wrote a regular function that attempted to increment i. [... details deleted ...] What do I need to do to update slot values? Here are some possibly relevant code fragments setClass(CompletePathMaker, representation(i=integer, timeOffset=numeric, # to avoid 0's truePaths=TruePaths) ) nextPath - function(pm){ #pm is a CompletePathMaker [EMAIL PROTECTED] - [EMAIL PROTECTED](1) [etc] I'm trying to make the class behave like an iterator, with i keeping track of its location. I'm sure there are more R'ish ways to go, but I'm also pretty sure I'm going to want to be able to update slots. Hello Ross, I see that your question was related to S4, but I just noticed a solution based on the R.oo package so I thought I would add a solution based on the proto package too. We had similar problems several times ago and (to my surprise) found R to be an extremely flexible language even for these things. Our favorite solution is available as package(proto). It requires R 2.1, because of several subtle improvements regarding environments, which made our implementation more streamlined. Does the following example do what you intended? ##= library(proto) ## 1) define an object CompletePathMaker - proto( index = 0, bumpIndex = function(., dindex = 1) .$index - .$index + as.integer(dindex) ) ## 2) create a child object of CompletePathMaker cpm - CompletePathMaker$proto() ## 3) set the index component to 3 cpm$index - 3 ## 4) iterate the index cpm$bumpIndex(2) ## print the result cpm$index ##= This approach is very compact and needs only one new function: proto. Also note how simple it is conceptually. We did not even create any classes. We just created a parent object CompletePathMaker and a child to it, cpm, and got everything else via delegation (i.e. inheritance). Hope it helps Thomas P. __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Ross Boylan wrote: On Sat, Jun 04, 2005 at 07:08:56PM +0200, Martin Maechler wrote: Ross nextPath - function(pm){ #pm is a CompletePathMaker Ross[EMAIL PROTECTED] - [EMAIL PROTECTED](1) Ross [etc] If your nextPath function has 'pm' as its last statement it will return the updated object, and if you call it as mypm - nextPath(mypm) you are 1) updating mypm 2) in a proper S way (i.e. no cheating). Regards, Martin Wow. This is almost the exact inverse of the usual object behavior, in which only the class itself can update the slots (aka instance variables). None of the methods of the class can update instances of the class persistently without the help of outsiders, and only outsiders can change the slot values. (Yes, I realize that using the idiom you suggest of returning a new object one can have only class methods actually fiddling with the slots.) The inability of a class method to change a class object without outside help seems unfortunate. It looks as if instances of class objects are best thought of as immutable once created. Obviously, there are many definition of object oriented programming, and yours seems to be different from the S4 definition. I was going to answer your first question at first, but you have not given enough details - in particular it was not clear to me why your approach did not work. I assumed that you are assigning the new object again, which is the S way. You have to think about scoping rules and it will be clear that the approach you are expecting is not a clean one in S. Uwe Ligges Ross __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
RE: [R] How to change the value of a class slot
On Mon, 2005-06-06 at 14:15 -0700, Berton Gunter wrote: I'm puzzled: It looks as if instances of class objects are best thought of as immutable once created. what then is setReplaceMethod() for? assignment operators do the whole object replacement behind the scenes, at least conceptually, as far as I can tell. I agree: they are mutators. But outside of this special case, it seems mutation of slots is difficult (i.e., requires the assistance of the caller). By the way, the documentation on setReplaceMethod does not actually say what it does. I found out by looking at the code. Second, in my experiments I couldn't get setReplacementMethod to work: bumpIndex- - function(pm, value) { [EMAIL PROTECTED] - [EMAIL PROTECTED](value) pm } # I get an error without the next function definition bumpIndex - function(pm) [EMAIL PROTECTED] setReplaceMethod(bumpIndex, signature=signature(pm=CompletePathMaker, value=numeric), bumpIndex) When I try to load this, I get arguments in definition changed from (spec) to (object) arguments in definition changed from (self) to (object) arguments in definition changed from (self) to (object) Creating a new generic function for 'bumpIndex-' in '.GlobalEnv' Error in conformMethod(signature, mnames, fnames, f) : In method for function bumpIndex-: formal arguments omitted in the method definition cannot be in the signature (value = numeric) All the errors are triggered by setReplaceMethod. Can anyone help me interpret them? Or, maybe better, tell me how to debug the compilation? I leave it to language experts to say whether S4 formal classes and methods are wise or not in comparison to others. From my fairly ignorant perspective, that always seems to be a matter of taste. There are actually two related issues on that score: first, whether the complex of expectation set up by talking about objects and classes are met by what R/S does, and second the wisdom of what R/S does in its own right. Cheers, Bert -- Ross Boylan wk: (415) 502-4031 530 Parnassus Avenue (Library) rm 115-4 [EMAIL PROTECTED] Dept of Epidemiology and Biostatistics fax: (415) 476-9856 University of California, San Francisco San Francisco, CA 94143-0840 hm: (415) 550-1062 __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
On Tue, 2005-06-07 at 08:36 +0200, Uwe Ligges wrote: Ross Boylan wrote: On Sat, Jun 04, 2005 at 07:08:56PM +0200, Martin Maechler wrote: Ross nextPath - function(pm){ #pm is a CompletePathMaker Ross[EMAIL PROTECTED] - [EMAIL PROTECTED](1) Ross [etc] If your nextPath function has 'pm' as its last statement it will return the updated object, and if you call it as mypm - nextPath(mypm) you are 1) updating mypm 2) in a proper S way (i.e. no cheating). Regards, Martin Wow. This is almost the exact inverse of the usual object behavior, in which only the class itself can update the slots (aka instance variables). None of the methods of the class can update instances of the class persistently without the help of outsiders, and only outsiders can change the slot values. (Yes, I realize that using the idiom you suggest of returning a new object one can have only class methods actually fiddling with the slots.) The inability of a class method to change a class object without outside help seems unfortunate. It looks as if instances of class objects are best thought of as immutable once created. Obviously, there are many definition of object oriented programming, and yours seems to be different from the S4 definition. Yes. And though there are many definitions of object oriented (at least, many implementations), I'd say the minimum requirement to be object oriented is to have objects that encapsulate both state (instance variables/slots) and behavior (methods). S4 objects do not fully encapsulate state because they require outside assistance to alter the state of the object (with the exception of assignment operators). The smalltalker in me also gets nervous that code outside the class can access the slots, but there are many object systems that act that way. The way in which names of methods of unrelated classes interfere with each other seems a break-down of the encapsulation of behavior, though the problem strictly is not with the behavior but just with the name. To return to the concrete problem that got me started, if class Specification defines a method likelihood taking as arguments instances of class Specification, Path and Parameters, then it is awkward to define a method likelihood for the class Model when that method has arguments of class Model, Specification, data.frame, and vector, particularly if different names for the formal arguments are desired. (I think technically it could be done, but only in a very ugly way--i.e., better to use different method names for the two classes). I was going to answer your first question at first, but you have not given enough details - in particular it was not clear to me why your approach did not work. I assumed that you are assigning the new object again, which is the S way. I wasn't, which is why it didn't work. I wanted the function to return some other value than the object it was operating on. You have to think about scoping rules and it will be clear that the approach you are expecting is not a clean one in S. Could you say a bit more about that? I had thought of the issue more in terms of function calls in S being call by value, preventing updates to the original arguments. So the issue isn't so much the scope of the names of function arguments (that scope being limited to the function body), but the properties of the thing they refer to (conceptually, a copy of the argument, not the original). __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
RE: [R] How to change the value of a class slot
Second, in my experiments I couldn't get setReplacementMethod to work: bumpIndex- - function(pm, value) { [EMAIL PROTECTED] - [EMAIL PROTECTED](value) pm } # I get an error without the next function definition bumpIndex - function(pm) [EMAIL PROTECTED] setReplaceMethod(bumpIndex, signature=signature(pm=CompletePathMaker, value=numeric), bumpIndex) 'bumpIndex' is apparently not a generic function (created by setGeneric) signature is not an argument to setReplaceMethod The ... argument to setReplaceMethod must include a function to do the replacement, which is why you need the bumpIndex function (I agree that this is not cleanly documented, but it's fairly easy to see since setReplaceMethod calls setMethod and that requires the function argument). so I don't see why you expect this to work at all. At the very least, shouldn't you do what the documentation tells you to? I think that you are expecting R to work according to your paradigm rather than trying to understand how it actually works. If you feel that R's paradigm (and/or documentation) is too awful to bother with, you might consider the R.oo package, which does OOP an entirely different way. -- Bert Gunter When I try to load this, I get arguments in definition changed from (spec) to (object) arguments in definition changed from (self) to (object) arguments in definition changed from (self) to (object) Creating a new generic function for 'bumpIndex-' in '.GlobalEnv' Error in conformMethod(signature, mnames, fnames, f) : In method for function bumpIndex-: formal arguments omitted in the method definition cannot be in the signature (value = numeric) All the errors are triggered by setReplaceMethod. Can anyone help me interpret them? Or, maybe better, tell me how to debug the compilation? I leave it to language experts to say whether S4 formal classes and methods are wise or not in comparison to others. From my fairly ignorant perspective, that always seems to be a matter of taste. There are actually two related issues on that score: first, whether the complex of expectation set up by talking about objects and classes are met by what R/S does, and second the wisdom of what R/S does in its own right. Cheers, Bert -- Ross Boylan wk: (415) 502-4031 530 Parnassus Avenue (Library) rm 115-4 [EMAIL PROTECTED] Dept of Epidemiology and Biostatistics fax: (415) 476-9856 University of California, San Francisco San Francisco, CA 94143-0840 hm: (415) 550-1062 __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Berton Gunter wrote: Second, in my experiments I couldn't get setReplacementMethod to work: bumpIndex- - function(pm, value) { [EMAIL PROTECTED] - [EMAIL PROTECTED](value) pm } # I get an error without the next function definition bumpIndex - function(pm) [EMAIL PROTECTED] setReplaceMethod(bumpIndex, signature=signature(pm=CompletePathMaker, value=numeric), bumpIndex) 'bumpIndex' is apparently not a generic function (created by setGeneric) signature is not an argument to setReplaceMethod The ... argument to setReplaceMethod must include a function to do the replacement, which is why you need the bumpIndex function (I agree that this is not cleanly documented, but it's fairly easy to see since setReplaceMethod calls setMethod and that requires the function argument). so I don't see why you expect this to work at all. At the very least, shouldn't you do what the documentation tells you to? I think that you are expecting R to work according to your paradigm rather than trying to understand how it actually works. If you feel that R's paradigm (and/or documentation) is too awful to bother with, you might consider the R.oo package, which does OOP an entirely different way. I have not followed the thread before, but here is an how it could look like with R.oo: setConstructorS3(CompletePathMaker, function(index=0) { extend(Object(), CompletePathMaker, index = as.integer(index) ) }) setMethodS3(increase, CompletePathMaker, function(this, dindex=+1) { this$index - this$index + as.integer(dindex); # You do not have to return anything here }) cpm - CompletePathMaker() cpm$index - 3 increase(cpm, 2) print(cpm$index) To add some control of what type of values you can assign to 'index', you can define a virtual field function setField(), e.g. setMethodS3(setIndex, CompletePathMaker, function(this, index) { if (!is.numeric(index) || length(index) != 1) stop(Argument 'index' must be a single numeric: , mode(index)); if (index 0) stop(Argument 'index' must be non-negative: , index); this$index - as.integer(index); # ... or here. }) cpm$index - 4 cpm$index - -3 # Gives an error as wanted! (Again...) note that setConstructorS3() and setMethodS3() are conveniency wrappers to define the CompletePathMaker(), increaseBumpIndex.CompletePathMaker() and setBumpIndex.CompletePathMaker(). The implementation of references is taken care of by the special class Object, which also implements support for virtual fields. /Henrik -- Bert Gunter When I try to load this, I get arguments in definition changed from (spec) to (object) arguments in definition changed from (self) to (object) arguments in definition changed from (self) to (object) Creating a new generic function for 'bumpIndex-' in '.GlobalEnv' Error in conformMethod(signature, mnames, fnames, f) : In method for function bumpIndex-: formal arguments omitted in the method definition cannot be in the signature (value = numeric) All the errors are triggered by setReplaceMethod. Can anyone help me interpret them? Or, maybe better, tell me how to debug the compilation? I leave it to language experts to say whether S4 formal classes and methods are wise or not in comparison to others. From my fairly ignorant perspective, that always seems to be a matter of taste. There are actually two related issues on that score: first, whether the complex of expectation set up by talking about objects and classes are met by what R/S does, and second the wisdom of what R/S does in its own right. Cheers, Bert -- Ross Boylan wk: (415) 502-4031 530 Parnassus Avenue (Library) rm 115-4 [EMAIL PROTECTED] Dept of Epidemiology and Biostatistics fax: (415) 476-9856 University of California, San Francisco San Francisco, CA 94143-0840 hm: (415) 550-1062 __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
RE: [R] How to change the value of a class slot [INFO]
On Tue, 2005-06-07 at 13:49 -0700, Berton Gunter wrote: Second, in my experiments I couldn't get setReplacementMethod to work: bumpIndex- - function(pm, value) { [EMAIL PROTECTED] - [EMAIL PROTECTED](value) pm } # I get an error without the next function definition bumpIndex - function(pm) [EMAIL PROTECTED] setReplaceMethod(bumpIndex, signature=signature(pm=CompletePathMaker, value=numeric), bumpIndex) ... When I try to load this, I get arguments in definition changed from (spec) to (object) arguments in definition changed from (self) to (object) arguments in definition changed from (self) to (object) Creating a new generic function for 'bumpIndex-' in '.GlobalEnv' Error in conformMethod(signature, mnames, fnames, f) : In method for function bumpIndex-: formal arguments omitted in the method definition cannot be in the signature (value = numeric) With some help from Bert, partly offlist, here's a working version: setReplaceMethod(bumpIndex, signature=signature(pm=CompletePathMaker, value=numeric), function(pm, value) { [EMAIL PROTECTED] - [EMAIL PROTECTED](value) pm }) At least 2 problems were caused by my original, final argument of bumpIndex to setReplaceMethod: 1) This looked for the function bumpIndex, not bumpIndex-. That's why I had to define the bumpIndex function. With the above change, it is no longer necessary to define bumpIndex. I needed to point it to bumpIndex-. I've been unable to find how to quote that properly. 2) The bumpIndex function doesn't have the right arguments. By the way, the use of value as the name for the final argument to the assignment function is mandatory. The info about value, as well as an extensive discussion of issues with mutating objects, appear in this 2003 tutorial by Gentleman: http://www.stat.auckland.ac.nz/S-Workshop/Gentleman/S4Objects.pdf (thanks to Bert for the pointer). Ross __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
On Sat, Jun 04, 2005 at 07:08:56PM +0200, Martin Maechler wrote: Ross nextPath - function(pm){ #pm is a CompletePathMaker Ross[EMAIL PROTECTED] - [EMAIL PROTECTED](1) Ross [etc] If your nextPath function has 'pm' as its last statement it will return the updated object, and if you call it as mypm - nextPath(mypm) you are 1) updating mypm 2) in a proper S way (i.e. no cheating). Regards, Martin Wow. This is almost the exact inverse of the usual object behavior, in which only the class itself can update the slots (aka instance variables). None of the methods of the class can update instances of the class persistently without the help of outsiders, and only outsiders can change the slot values. (Yes, I realize that using the idiom you suggest of returning a new object one can have only class methods actually fiddling with the slots.) The inability of a class method to change a class object without outside help seems unfortunate. It looks as if instances of class objects are best thought of as immutable once created. Ross __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Re: [R] How to change the value of a class slot
Ross == Ross Boylan [EMAIL PROTECTED] on Fri, 03 Jun 2005 17:04:08 -0700 writes: Ross I defined an S4 class with a slot i. Then I wrote a regular function Ross that attempted to increment i. Ross This didn't work, apparently because of the general rule that a function Ross can't change the values of its arguments outside the function. I gather Ross there are ways around it, but the Green book admonishes cheating on the Ross S evaluation model is to be avoided (p. 190). Ross Thinking that class methods needed to an exception to this rule, I then Ross tried setMethod with the function I had written. However, when I called Ross the function I got setMethod(nextPath, CompletePathMaker, nextPath) Ross Creating a new generic function for 'nextPath' in '.GlobalEnv' Ross [1] nextPath nextPath(pm) Ross Error: protect(): protection stack overflow Ross I can change the value of the slot interactively, so the problem does Ross not appear to be that the slots are considered off-limits. Ross What do I need to do to update slot values? Ross Here are some possibly relevant code fragments Ross setClass(CompletePathMaker, Ross representation(i=integer, Ross timeOffset=numeric, # to avoid 0's Ross truePaths=TruePaths) Ross ) Ross nextPath - function(pm){ #pm is a CompletePathMaker Ross[EMAIL PROTECTED] - [EMAIL PROTECTED](1) Ross [etc] If your nextPath function has 'pm' as its last statement it will return the updated object, and if you call it as mypm - nextPath(mypm) you are 1) updating mypm 2) in a proper S way (i.e. no cheating). Regards, Martin Ross I'm trying to make the class behave like an iterator, with i keeping Ross track of its location. I'm sure there are more R'ish ways to go, but Ross I'm also pretty sure I'm going to want to be able to update slots. Ross Thanks. Ross Ross Boylan __ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html