From winstonchang1 at gmail.com  Wed Oct 16 21:47:30 2013
From: winstonchang1 at gmail.com (Winston Chang)
Date: Wed, 16 Oct 2013 14:47:30 -0500
Subject: [Rd] Internally accessing ref class methods with .self$x is
	different from .self[['x']]
Message-ID: <CAFOpNVHwYJRXtwk0Y3v9RvFY9=B+na81MnCBHzMc2Y7SKBPekg@mail.gmail.com>

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"         "e"         "tc"        "TestClass"
==================== .self[['a']] ====================
An object of class "uninitializedField"
Slot "field":
[1] "a"

Slot "className":
[1] "ANY"

==================== .self[['b']] ====================
NULL
==================== b ====================
function() {
      "Yes, this is b."
    }
==================== .self$b ====================
function() {
      "Yes, this is b."
    }
<environment: 0x5a65418>
attr(,"mayCall")
character(0)
attr(,"name")
[1] "b"
attr(,"refClassName")
[1] "TestClass"
attr(,"superClassMethod")
[1] ""
attr(,"class")
[1] "refMethodDef"
attr(,"class")attr(,"package")
[1] "methods"
==================== .self[['b']] ====================
function() {
      "Yes, this is b."
    }
<environment: 0x5a65418>
attr(,"mayCall")
character(0)
attr(,"name")
[1] "b"
attr(,"refClassName")
[1] "TestClass"
attr(,"superClassMethod")
[1] ""
attr(,"class")
[1] "refMethodDef"
attr(,"class")attr(,"package")
[1] "methods"
==================== b ====================
function() {
      "Yes, this is b."
    }
<environment: 0x5a65418>
attr(,"mayCall")
character(0)
attr(,"name")
[1] "b"
attr(,"refClassName")
[1] "TestClass"
attr(,"superClassMethod")
[1] ""
attr(,"class")
[1] "refMethodDef"
attr(,"class")attr(,"package")
[1] "methods"
===============================================
[1] "a"          "b"          "initialize"
[1] "b"         "e"         "tc"        "TestClass"



-Winston



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