On 09/24/2011 08:55 AM, henry wrote:
Greetings,

I am trying to use Reference Class methods in Snowfall, using R 2.12.1
on Ubuntu Natty. Using then directly seems to work (stanza 2 below), but
using them indirectly does not (stanza 3 below). I get an "attempt to
apply non-function" error.

In addition to exporting the instance of the object I created to the
Snowfall slaves, I also made several attempts to export the method
itself (e.g. sfExport("instance$method") or some such), with no success.
Very strangely, if I run Stanza 2 below, then stanza 3 will work.

I tried emailing the Snowfall author, but have not heard back. Any help
is greatly appreciated!

Henry Bryant
Texas A&M University



library("snowfall")
library("methods")

# set up a simple reference class
calculator <- setRefClass("calculator")
calculator$methods(do_calc = function(x) {print(x*x)})
my_calc <- calculator$new()
wrapper <- function(x) {my_calc$do_calc(x)}

# STANZA 2: use snowfall without wrapper -- WORKING
#sfInit(parallel=TRUE, cpus=2, type="SOCK")
#sfExport("calculator")
#sfExport("my_calc")
#results <- sfLapply(1:10,my_calc$do_calc)
#sfStop()
#print(results)

# STANZA 3: use snowfall with wrapper -- NOT WORKING
# (not working by itself, but does work if the previous stanza is run
first!!)
sfInit(parallel=TRUE, cpus=2, type="SOCK")
sfExport("calculator")
sfExport("my_calc")
sfExport("wrapper")
last_results <- sfLapply(1:10,wrapper)

Hi Henry --

The problem here is that references classes implement their methods in a kind of 'lazy' way -- my_calc$do_calc doesn't exist until it's actually invoked for the first time, so when you

  sfExport("my_calc")

you export the object but "do_calc" is defined as NULL

> sfClusterEval(my_calc$do_calc)
[[1]]
NULL

[[2]]
NULL

This seems to be a variant of the problem experienced elsewhere

https://stat.ethz.ch/pipermail/r-devel/2011-June/061260.html
http://stackoverflow.com/questions/7331518/method-initialisation-in-r-reference-classes

The solutions seem mostly ugly, e.g., to evaluate locally

> my_calc$do_calc

and then sfExport, or maybe a bit better as

calculator <- setRefClass("calculator")
calculator$methods(
    initialize = function(...) {
        callSuper(...)
        .self$do_calc                   # force definition
        .self
    },
    do_calc = function(x) x*x)

I'm unclear about whether there are other aspects of the reference class implementation that tie the instance to the class definition in a way that would undermine parallel evaluation.

Also in general it seems better to write truly 'functional programming' style functions that don't rely on aspects of the environment to work, e.g.,

  wrapper <- function(x, calc) calc$do_calc(x)
  sfLapply(1:10, wrapper, my_calc)

Martin

sfStop()
cat("\nRESULTS FROM SECOND TRY:\n")
print(last_results)

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.


--
Computational Biology
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109

Location: M1-B861
Telephone: 206 667-2793

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to