Reference Classes: Generalizing Reference Class Generator objects?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Reference Classes: Generalizing Reference Class Generator objects?

Daniel Lee
Is it possible to override the $new(...) in the reference class
generator? I have tried adding a "new" method to the methods of the
class, but that is obviously not correct. I have also tried adding it to
the class generator, but the class generator still uses the default
constructor.

As a simple example, this is the current interface:
TestClass <- setRefClass ("TestClass",
         fields = list (text = "character"),
         methods = list (
                 print = function ()  {cat(text)})
)
test <- TestClass$new (text="Hello World")
test$print()

I would like to override $new(...) to be something like (add a "\n" to
the end of the input, no need to specify input fields):
TestClass$methods (new = function (text) {
             text <- paste (text, "\n")
             methods:::new (def, text=text)
         })

The constructor would then be:
test <- TestClass$new ("Hello World")

This is a subtle, but useful change. I have also tried adding to
TestClass a method $newInstance(text), but that was not successful. If
this is not possible, could we consider augmenting the Reference Class
interface to include constructors?

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Reference Classes: Generalizing Reference Class Generator objects?

Jon Clayden
Hi Daniel,

I think you want to define an "initialize" method, as in

TestClass <- setRefClass ("TestClass",
       fields = list (text = "character"),
       methods = list (
               initialize = function (text) { object <-
initFields(text=paste(text,"\n")) },
               print = function ()  { cat(text) } )
)

This seems to work as you intend:

> x <- TestClass$new("test")
> x$print()
test


All the best,
Jon

On 28 October 2010 15:13, Daniel Lee <[hidden email]> wrote:

> Is it possible to override the $new(...) in the reference class generator? I
> have tried adding a "new" method to the methods of the class, but that is
> obviously not correct. I have also tried adding it to the class generator,
> but the class generator still uses the default constructor.
>
> As a simple example, this is the current interface:
> TestClass <- setRefClass ("TestClass",
>        fields = list (text = "character"),
>        methods = list (
>                print = function ()  {cat(text)})
> )
> test <- TestClass$new (text="Hello World")
> test$print()
>
> I would like to override $new(...) to be something like (add a "\n" to the
> end of the input, no need to specify input fields):
> TestClass$methods (new = function (text) {
>            text <- paste (text, "\n")
>            methods:::new (def, text=text)
>        })
>
> The constructor would then be:
> test <- TestClass$new ("Hello World")
>
> This is a subtle, but useful change. I have also tried adding to TestClass a
> method $newInstance(text), but that was not successful. If this is not
> possible, could we consider augmenting the Reference Class interface to
> include constructors?
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Reference Classes: Generalizing Reference Class Generator objects?

Jon Clayden
In reply to this post by Daniel Lee
Sorry - you don't need to assign the value of initFields(). I was
going to do it in two lines but then realised one was enough... :)

TestClass <- setRefClass ("TestClass",
       fields = list (text = "character"),
       methods = list (
               initialize = function (text) {
initFields(text=paste(text,"\n")) },
               print = function ()  { cat(text) } )
)

All the best,
Jon


On 28 October 2010 15:13, Daniel Lee <[hidden email]> wrote:

> Is it possible to override the $new(...) in the reference class generator? I
> have tried adding a "new" method to the methods of the class, but that is
> obviously not correct. I have also tried adding it to the class generator,
> but the class generator still uses the default constructor.
>
> As a simple example, this is the current interface:
> TestClass <- setRefClass ("TestClass",
>        fields = list (text = "character"),
>        methods = list (
>                print = function ()  {cat(text)})
> )
> test <- TestClass$new (text="Hello World")
> test$print()
>
> I would like to override $new(...) to be something like (add a "\n" to the
> end of the input, no need to specify input fields):
> TestClass$methods (new = function (text) {
>            text <- paste (text, "\n")
>            methods:::new (def, text=text)
>        })
>
> The constructor would then be:
> test <- TestClass$new ("Hello World")
>
> This is a subtle, but useful change. I have also tried adding to TestClass a
> method $newInstance(text), but that was not successful. If this is not
> possible, could we consider augmenting the Reference Class interface to
> include constructors?
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Reference Classes: Generalizing Reference Class Generator objects?

Daniel Lee
Thank you. Your example really clarifies what the $initialize(...)
function is supposed to do.

Do you know if there is a straightforward way to dispatch the $new(...)
method based on the signature of the arguments? I am thinking along the
lines of S4 methods with valid signatures.

Thanks again for the example.


On 10/28/2010 12:12 PM, Jon Clayden wrote:

> Sorry - you don't need to assign the value of initFields(). I was
> going to do it in two lines but then realised one was enough... :)
>
> TestClass<- setRefClass ("TestClass",
>         fields = list (text = "character"),
>         methods = list (
>                 initialize = function (text) {
> initFields(text=paste(text,"\n")) },
>                 print = function ()  { cat(text) } )
> )
>
> All the best,
> Jon
>
>
> On 28 October 2010 15:13, Daniel Lee<[hidden email]>  wrote:
>> Is it possible to override the $new(...) in the reference class generator? I
>> have tried adding a "new" method to the methods of the class, but that is
>> obviously not correct. I have also tried adding it to the class generator,
>> but the class generator still uses the default constructor.
>>
>> As a simple example, this is the current interface:
>> TestClass<- setRefClass ("TestClass",
>>         fields = list (text = "character"),
>>         methods = list (
>>                 print = function ()  {cat(text)})
>> )
>> test<- TestClass$new (text="Hello World")
>> test$print()
>>
>> I would like to override $new(...) to be something like (add a "\n" to the
>> end of the input, no need to specify input fields):
>> TestClass$methods (new = function (text) {
>>             text<- paste (text, "\n")
>>             methods:::new (def, text=text)
>>         })
>>
>> The constructor would then be:
>> test<- TestClass$new ("Hello World")
>>
>> This is a subtle, but useful change. I have also tried adding to TestClass a
>> method $newInstance(text), but that was not successful. If this is not
>> possible, could we consider augmenting the Reference Class interface to
>> include constructors?
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Reference Classes: Generalizing Reference Class Generator objects?

Jon Clayden
?ReferenceClasses says "Reference methods can not themselves be
generic functions; if you want additional function-based method
dispatch, write a separate generic function and call that from the
method". So I think you'd need to take that approach in your
"initialize" method.

Hope this helps,
Jon


On 28 October 2010 18:25, Daniel Lee <[hidden email]> wrote:

> Thank you. Your example really clarifies what the $initialize(...) function
> is supposed to do.
>
> Do you know if there is a straightforward way to dispatch the $new(...)
> method based on the signature of the arguments? I am thinking along the
> lines of S4 methods with valid signatures.
>
> Thanks again for the example.
>
>
> On 10/28/2010 12:12 PM, Jon Clayden wrote:
>>
>> Sorry - you don't need to assign the value of initFields(). I was
>> going to do it in two lines but then realised one was enough... :)
>>
>> TestClass<- setRefClass ("TestClass",
>>        fields = list (text = "character"),
>>        methods = list (
>>                initialize = function (text) {
>> initFields(text=paste(text,"\n")) },
>>                print = function ()  { cat(text) } )
>> )
>>
>> All the best,
>> Jon
>>
>>
>> On 28 October 2010 15:13, Daniel Lee<[hidden email]>  wrote:
>>>
>>> Is it possible to override the $new(...) in the reference class
>>> generator? I
>>> have tried adding a "new" method to the methods of the class, but that is
>>> obviously not correct. I have also tried adding it to the class
>>> generator,
>>> but the class generator still uses the default constructor.
>>>
>>> As a simple example, this is the current interface:
>>> TestClass<- setRefClass ("TestClass",
>>>        fields = list (text = "character"),
>>>        methods = list (
>>>                print = function ()  {cat(text)})
>>> )
>>> test<- TestClass$new (text="Hello World")
>>> test$print()
>>>
>>> I would like to override $new(...) to be something like (add a "\n" to
>>> the
>>> end of the input, no need to specify input fields):
>>> TestClass$methods (new = function (text) {
>>>            text<- paste (text, "\n")
>>>            methods:::new (def, text=text)
>>>        })
>>>
>>> The constructor would then be:
>>> test<- TestClass$new ("Hello World")
>>>
>>> This is a subtle, but useful change. I have also tried adding to
>>> TestClass a
>>> method $newInstance(text), but that was not successful. If this is not
>>> possible, could we consider augmenting the Reference Class interface to
>>> include constructors?
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Reference Classes: Generalizing Reference Class Generator objects?

John Chambers-2
Good diagnoses.

This thread brought up a point or two that needed some fixes to the
documentation and code.  They should be in r-devel and 2.12 patched
(from rev. 53471).

Briefly:

- Initialization methods should take account of future subclasses to
your class by including and passing on the ... argument, so that
additional fields can be specified.  Discussed briefly now in the
$new(...) section of ?ReferenceClasses.

- The InitFields() method is fine but was an early kludge when
callSuper() didn't work for initialize().  To allow for the case that
your class has a superclass with an initialize() method, use the
callSuper() approach.  There is an example now in the documentation.

John

On 10/28/10 10:55 AM, Jon Clayden wrote:

> ?ReferenceClasses says "Reference methods can not themselves be
> generic functions; if you want additional function-based method
> dispatch, write a separate generic function and call that from the
> method". So I think you'd need to take that approach in your
> "initialize" method.
>
> Hope this helps,
> Jon
>
>
> On 28 October 2010 18:25, Daniel Lee<[hidden email]>  wrote:
>> Thank you. Your example really clarifies what the $initialize(...) function
>> is supposed to do.
>>
>> Do you know if there is a straightforward way to dispatch the $new(...)
>> method based on the signature of the arguments? I am thinking along the
>> lines of S4 methods with valid signatures.
>>
>> Thanks again for the example.
>>
>>
>> On 10/28/2010 12:12 PM, Jon Clayden wrote:
>>>
>>> Sorry - you don't need to assign the value of initFields(). I was
>>> going to do it in two lines but then realised one was enough... :)
>>>
>>> TestClass<- setRefClass ("TestClass",
>>>         fields = list (text = "character"),
>>>         methods = list (
>>>                 initialize = function (text) {
>>> initFields(text=paste(text,"\n")) },
>>>                 print = function ()  { cat(text) } )
>>> )
>>>
>>> All the best,
>>> Jon
>>>
>>>
>>> On 28 October 2010 15:13, Daniel Lee<[hidden email]>    wrote:
>>>>
>>>> Is it possible to override the $new(...) in the reference class
>>>> generator? I
>>>> have tried adding a "new" method to the methods of the class, but that is
>>>> obviously not correct. I have also tried adding it to the class
>>>> generator,
>>>> but the class generator still uses the default constructor.
>>>>
>>>> As a simple example, this is the current interface:
>>>> TestClass<- setRefClass ("TestClass",
>>>>         fields = list (text = "character"),
>>>>         methods = list (
>>>>                 print = function ()  {cat(text)})
>>>> )
>>>> test<- TestClass$new (text="Hello World")
>>>> test$print()
>>>>
>>>> I would like to override $new(...) to be something like (add a "\n" to
>>>> the
>>>> end of the input, no need to specify input fields):
>>>> TestClass$methods (new = function (text) {
>>>>             text<- paste (text, "\n")
>>>>             methods:::new (def, text=text)
>>>>         })
>>>>
>>>> The constructor would then be:
>>>> test<- TestClass$new ("Hello World")
>>>>
>>>> This is a subtle, but useful change. I have also tried adding to
>>>> TestClass a
>>>> method $newInstance(text), but that was not successful. If this is not
>>>> possible, could we consider augmenting the Reference Class interface to
>>>> include constructors?
>>>>
>>>> ______________________________________________
>>>> [hidden email] mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>
>>
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Reference Classes: Generalizing Reference Class Generator objects?

Vitalie S.-2
John Chambers <[hidden email]> writes:

> Good diagnoses.
>
> This thread brought up a point or two that needed some fixes to the documentation and code.  They should be in
> r-devel and 2.12 patched (from rev. 53471).
>
> Briefly:
>
> - Initialization methods should take account of future subclasses to your class by including and passing on the
> ... argument, so that additional fields can be specified.  Discussed briefly now in the $new(...) section of
> ?ReferenceClasses.
>
> - The InitFields() method is fine but was an early kludge when callSuper() didn't work for initialize().  To allow
> for the case that your class has a superclass with an initialize() method, use the callSuper() approach.  There is
> an example now in the documentation.

What about, extending the generator class in general? Looking at the source I
can infer that there is little that can be done about it (except rewriting the
setRefClass function itself). Does that mean that the refObjectGenerator class is
not supposed to be extended?

Also, tangentially related to above, why generator objects in the first place?
It might have been implemented as S4 class with the slot "def" to hold the
representation of refClasses. No additional generators would hang around,
extension of generators would be easier and departure from S4 would be minimal.

The only reason I could think off, is the inability to write ref style methods
for it. But, I must be definitely missing something here.

Thanks,
Vitalie.

>
> On 10/28/10 10:55 AM, Jon Clayden wrote:
>> ?ReferenceClasses says "Reference methods can not themselves be
>> generic functions; if you want additional function-based method
>> dispatch, write a separate generic function and call that from the
>> method". So I think you'd need to take that approach in your
>> "initialize" method.
>>
>> Hope this helps,
>> Jon
>>
>>
>> On 28 October 2010 18:25, Daniel Lee<[hidden email]>  wrote:
>>> Thank you. Your example really clarifies what the $initialize(...) function
>>> is supposed to do.
>>>
>>> Do you know if there is a straightforward way to dispatch the $new(...)
>>> method based on the signature of the arguments? I am thinking along the
>>> lines of S4 methods with valid signatures.
>>>
>>> Thanks again for the example.
>>>
>>>
>>> On 10/28/2010 12:12 PM, Jon Clayden wrote:
>>>>
>>>> Sorry - you don't need to assign the value of initFields(). I was
>>>> going to do it in two lines but then realised one was enough... :)
>>>>
>>>> TestClass<- setRefClass ("TestClass",
>>>>         fields = list (text = "character"),
>>>>         methods = list (
>>>>                 initialize = function (text) {
>>>> initFields(text=paste(text,"\n")) },
>>>>                 print = function ()  { cat(text) } )
>>>> )
>>>>
>>>> All the best,
>>>> Jon
>>>>
>>>>
>>>> On 28 October 2010 15:13, Daniel Lee<[hidden email]>    wrote:
>>>>>
>>>>> Is it possible to override the $new(...) in the reference class
>>>>> generator? I
>>>>> have tried adding a "new" method to the methods of the class, but that is
>>>>> obviously not correct. I have also tried adding it to the class
>>>>> generator,
>>>>> but the class generator still uses the default constructor.
>>>>>
>>>>> As a simple example, this is the current interface:
>>>>> TestClass<- setRefClass ("TestClass",
>>>>>         fields = list (text = "character"),
>>>>>         methods = list (
>>>>>                 print = function ()  {cat(text)})
>>>>> )
>>>>> test<- TestClass$new (text="Hello World")
>>>>> test$print()
>>>>>
>>>>> I would like to override $new(...) to be something like (add a "\n" to
>>>>> the
>>>>> end of the input, no need to specify input fields):
>>>>> TestClass$methods (new = function (text) {
>>>>>             text<- paste (text, "\n")
>>>>>             methods:::new (def, text=text)
>>>>>         })
>>>>>
>>>>> The constructor would then be:
>>>>> test<- TestClass$new ("Hello World")
>>>>>
>>>>> This is a subtle, but useful change. I have also tried adding to
>>>>> TestClass a
>>>>> method $newInstance(text), but that was not successful. If this is not
>>>>> possible, could we consider augmenting the Reference Class interface to
>>>>> include constructors?
>>>>>
>>>>> ______________________________________________
>>>>> [hidden email] mailing list
>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel>>>>
>>>
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel