From soeren.vogel at uzh.ch  Sat Jun  4 16:54:46 2011
From: soeren.vogel at uzh.ch (soeren.vogel at uzh.ch)
Date: Sat, 4 Jun 2011 16:54:46 +0200
Subject: [Rd] S4 class, passing argument names to function,
	modify original
In-Reply-To: <4DEA35F1.7020208@fhcrc.org>
References: <C6C4A88B-761A-46F0-90E3-24260973F699@uzh.ch>
	<4DEA35F1.7020208@fhcrc.org>
Message-ID: <BD4BEC8E-6A02-4B9B-AFA9-9796008A4A56@uzh.ch>

On 04.06.2011, at 15:41, Martin Morgan wrote:

> On 06/04/2011 03:07 AM, soeren.vogel at uzh.ch wrote:
> 
>> Hello, an S4 class "Foo" is defined with a setter, $. For several reasons, the setter calls a function, .foo.update(). However, bypassing the argument names of the setter does not work. Question 1: Why not and how can I fix this? Question 2: What is the way to define either the function or the setter to modify the original object (not returning the modified copy of it an overwrite the original by assignment)? Thanks, S?ren
>> 
>> setClass("Foo",
>>   representation(
>>     N = "numeric"
>>   ),
>>   prototype(
>>     N = 10000
>>   )
>> )
>> 
>> .foo.update<- function(object, ...) {
>>   args<- list(...)
>>   for (i in slotNames("Foo")[pmatch(names(args), slotNames("Foo"), nomatch=0)]) {
>>     slot(object, i)<- args[[i]]
>>     # indeed more to do here
>>     return(object)
>>   }
>> }
> 
> Since names(args) is 'name', and 'name' is not a slot of 'Foo', the return of pmatch is 0 and .foo.update returns NULL. Put return(object) outside the for loop.
> 
>> setReplaceMethod("$", "Foo",
>>   function(x, name, value) {
>>     x<- .foo.update(x, name=value)
>>     x
>>   }
>> )
>> 
>> x<- new("Foo")
>> x
>> x$N<- 99
>> x # NULL????
> 
> here your intention is that name=value to be substituted with N=99, but you end up with name=99. You could arrange to parse this correctly, but this isn't usually what you _want_ to do and I don't really understand what you're trying to accomplish.

Exactly, what I want to parse is "N"=99. To clarify, .foo.update should be the "one" workhorse to do a couple of things depending on arguments on more than one object (see my post on interfacing a C++ class, just some minutes ago). Thus, assigning x at N = 10 (x$N, x["N"]) should not only end up in x (object of class Foo) with value 10, but also should invoke FOO$setN(10) (a setter for the C++ object, not shown here). So far, .foo.update works perfectly and indeed alters the object x, but the setter does not parse the argument name. I tried with quote, substitute, deparse ..., but got none working ...

> Maybe
> 
> .foo.update <- function(object, name, value, ...)
> {
>    slot(object, name) <- value
>    ## some other stuff
>    object
> }
> 
> Hope that helps a bit.
> 
> Martin

Thanks, S?ren



[Rd] S4 class, passing argument names to function, modify original
soeren.vogel at uzh.ch