Re: [Rd] Internally accessing ref class methods with .self$x is different from .self[['x']]

2013-10-16 Thread Gabriel Becker
Winston,

Sounds like you might be better of constructing and evaluating an
expression:

> test = setRefClass("test", methods = list(m1 = function() "hi", m2 =
function() "lo", byname = function(nm) {
+ expr = substitute(.self$xXx(), list(xXx = nm))
+ eval(expr)
+ }))
> thing = test$new()
> thing$byname("m1")
[1] "hi"

HTH,
~G



On Wed, Oct 16, 2013 at 2:12 PM, Winston Chang wrote:

> On Wed, Oct 16, 2013 at 3:41 PM, Gabriel Becker 
> wrote:
> > Winston,
> >
> >  (back on list since I found some official info)
> >
> > Looks like the behavior you are seeing is "documented-ish"
> >
> > Only methods actually used will be included in the environment
> corresponding
> > to an individual object. To declare that a method requires a particular
> > other method, the first method should include a call to $usingMethods()
> with
> > the name of the other method as an argument. Declaring the methods this
> way
> > is essential if the other method is used indirectly (e.g., via sapply()
> or
> > do.call()). If it is called directly, code analysis will find it.
> Declaring
> > the method is harmless in any case, however, and may aid readability of
> the
> > source code.
> >
> > Seems like .self$usingMethods() is supposed to allow you to do what you
> > want, but I wasn't able to get it to work after a few minutes of fiddling
> > and the actual usingMethods method doesn't seem to do anything on cursory
> > inspection in a toy example but I don't pretend to know the arcane
> depths of
> > the refclass machinery.
> >
>
> I wasn't able to get .self$usingMethods() to work either. I think that
> for my case, it still won't do the job - the issue is that I'm calling
> a method and passing the name of another method, which is accessed via
> [[. Since .self$usingMethods() supposedly analyzes code when the class
> is installed (and not at runtime), that wouldn't help in this case.
>
> Previously I said that code like this would work, but I was wrong:
>   var <- "someMethod"
>   `$`(.self, var)
> It doesn't work because $ doesn't evaluate var; it thinks you're
> trying to get .self$var, not .self$someMethod.
>
> The workaround we're using for now is:
>   do.call(`$`, list(.self, var))
>
> -Winston
>



-- 
Gabriel Becker
Graduate Student
Statistics Department
University of California, Davis

[[alternative HTML version deleted]]

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


Re: [Rd] Internally accessing ref class methods with .self$x is different from .self[['x']]

2013-10-16 Thread Winston Chang
On Wed, Oct 16, 2013 at 3:41 PM, Gabriel Becker  wrote:
> Winston,
>
>  (back on list since I found some official info)
>
> Looks like the behavior you are seeing is "documented-ish"
>
> Only methods actually used will be included in the environment corresponding
> to an individual object. To declare that a method requires a particular
> other method, the first method should include a call to $usingMethods() with
> the name of the other method as an argument. Declaring the methods this way
> is essential if the other method is used indirectly (e.g., via sapply() or
> do.call()). If it is called directly, code analysis will find it. Declaring
> the method is harmless in any case, however, and may aid readability of the
> source code.
>
> Seems like .self$usingMethods() is supposed to allow you to do what you
> want, but I wasn't able to get it to work after a few minutes of fiddling
> and the actual usingMethods method doesn't seem to do anything on cursory
> inspection in a toy example but I don't pretend to know the arcane depths of
> the refclass machinery.
>

I wasn't able to get .self$usingMethods() to work either. I think that
for my case, it still won't do the job - the issue is that I'm calling
a method and passing the name of another method, which is accessed via
[[. Since .self$usingMethods() supposedly analyzes code when the class
is installed (and not at runtime), that wouldn't help in this case.

Previously I said that code like this would work, but I was wrong:
  var <- "someMethod"
  `$`(.self, var)
It doesn't work because $ doesn't evaluate var; it thinks you're
trying to get .self$var, not .self$someMethod.

The workaround we're using for now is:
  do.call(`$`, list(.self, var))

-Winston

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


Re: [Rd] Internally accessing ref class methods with .self$x is different from .self[['x']]

2013-10-16 Thread Gabriel Becker
Winston,

 (back on list since I found some official info)

Looks like the behavior you are seeing is "documented-ish"

Only methods actually used will be included in the environment
corresponding to an individual object. To declare that a method requires a
particular other method, the first method should include a call to
$usingMethods() with the name of the other method as an argument. Declaring
the methods this way is essential if the other method is used indirectly
(e.g., via 
sapply
() or 
do.call
()). If it is called directly, code analysis will find it. Declaring the
method is harmless in any case, however, and may aid readability of the
source code.

Seems like .self$usingMethods() is supposed to allow you to do what you
want, but I wasn't able to get it to work after a few minutes of fiddling
and the actual usingMethods method doesn't seem to do anything on cursory
inspection in a toy example but I don't pretend to know the arcane depths
of the refclass machinery.

~G


On Wed, Oct 16, 2013 at 1:14 PM, Winston Chang wrote:

> Hi Gabriel -
>
> Thanks for your reply. The reason that I'm interested in doing it that
> way is because we're working on a project where we call a method and
> pass it the name of another method, and that method is accessed with $
> or [[.
>
> You might be right about [[ treating it as a standard environment.
> Reading the docs a little more closely, I found:
> "... The corresponding programming mechanism is to invoke a method on
> an object. In the R syntax we use "$" for this operation; one invokes
> a method, m1 say, on an object x by the expression x$m1(...)."
>
> This works as expected, but it is a bit clunky:
> `$`(.self, x)
>
> -Winston
>
>
> On Wed, Oct 16, 2013 at 3:08 PM, Gabriel Becker 
> wrote:
> > Winston,
> >
> > Replying off list as I'm not an expert and don't have time to delve into
> > this enough to actually track it down.
> >
> > Is there a reason to expect [[ to work in this way? I've only ever
> > seen/written code that access fields/methods on reference classes via $
> > (which I assume has extra machinery for RefClasses to deal with active
> > binding functions for fields, etc).
> >
> > My guess would be that [[ is treating the reference class obj as a
> standard
> > environment which is bypassing some extra step necessary for refclass
> > objects and that is causing the problems.
> >
> >
> > I'd say its probably still a bug, but of the "why were you trying to do
> > that?" variety (no offense intended to you at all).
> >
> > All I can really suggest in the interim is to just use $ instead until
> John
> > (Chambers) pops up and responds to your mail.
> >
> > ~G
> >
> >
> > On Wed, Oct 16, 2013 at 12:47 PM, Winston Chang  >
> > wrote:
> >>
> >> When a reference class method is accessed with .self$x, it has
> >> different behavior from .self[['x']]. The former copies the function
> >> to the object's environment (with some attributes attached), and the
> >> latter just return NULL (unless it has already been accessed once with
> >> .self$x). Is this how it's supposed to work?
> >>
> >> Here's an example that illustrates: https://gist.github.com/wch/7013262
> >>
> >> TestClass <- setRefClass(
> >>   'TestClass',
> >>   fields = list(a = 'ANY'),
> >>   methods = list(
> >> initialize = function() {
> >>   e <- environment()
> >>   pe <- parent.env(e)
> >>   ppe <- parent.env(pe)
> >>
> >>   # The environment of this object
> >>   print(ls(pe))
> >>   # The environment of the class
> >>   print(ls(ppe))
> >>
> >>   # No surprises with fields
> >>   cat(" .self[['a']] \n")
> >>   print(.self[['a']])
> >>
> >>
> >>   # Getting b these ways isn't quite what we want
> >>   cat(" .self[['b']] \n")
> >>   print(.self[['b']])
> >>   cat(" b \n")
> >>   print(b)
> >>
> >>
> >>   # Accessing b with $ works, and it changes things from here on in
> >>   cat(" .self$b \n")
> >>   print(.self$b)
> >>
> >>
> >>   # Now these return the b method with some attributes attached
> >>   cat(" .self[['b']] \n")
> >>   print(.self[['b']])
> >>   cat(" b \n")
> >>   print(b)
> >>
> >>
> >>   cat("===\n")
> >>   print(ls(parent.env(e)))
> >>   print(ls(parent.env(parent.env(e
> >>
> >> },
> >>
> >> b = function() {
> >>   "Yes, this is b."
> >> }
> >>   )
> >> )
> >>
> >> tc <- TestClass$new()
> >>
> >>
> >> Output:
> >> 
> >>
> >> [1] "a"  "initialize"
> >> [1] "b"