On Tue, Feb 21, 2012 at 12:15 AM, Ben quant <ccqu...@gmail.com> wrote: > Thanks again for your so far on proto. I have another question. > > What is the best way to "do stuff" based on data prior to calling a > function? I tried the code below without expr (and including commas after > data member assignments), but it errors out. I'd like to make decisions > based on inputs during proto object construction and prep my data_members > for use in the functions that (would) follow. I think I could probably get > around this with a small function with other functions within the same proto > object, but I'd rather not repeat that in each function...if that makes > sense. See my last line of code below: > > makeProto = proto( expr={ > data_member1=NULL > data_member2=5 > data_member3=NULL > if(!is.null(data_member1)){ > with(.,data_member3 = data_member1 + data_member2) > } > }) > oo = makeProto$proto() > oo$data_member1 # NULL > oo$data_member2 # 5 > oo$data_member3 # NULL > oo2 = makeProto$proto(data_member1 = 7) > oo2$data_member1 # 7 > oo2$data_member2 # 5 > oo2$data_member3 # I want this to be 12 (12 = 7 + 5), but I get NULL > > Its late for me so hopefully this makes sense... >
There are multiple issues here: 1. The expr is executed at the time you define the proto object -- its not a method. Once the proto object is defined the only thing that is left is the result of the computation so you can't spawn a child and then figure that this code will be rerun as if its a constructor. You need to define a constructor method to do that. 2. You can't use dot as if it were a special notation -- its not. A single dot is just the name of an ordinary variable and is not anything special that proto knows about. In the examples where dot is used its used as the first formal argument to various methods but this was the choice of the method writer and not something required by proto. We could have used self or this or any variable name. 3. Note that the code in expr=... is already evaluated in the environment of the proto object so you don't need with. 4. I personally find it clearer to reserve = for argument assignment and use <- for ordinary assignment but that is mostly a style issue and its up to you: 5. The discussion of traits in the proto vignette illustrates constructors -- be sure to read that. Traits are not a special construct built into proto but rather its just a way in which you can use proto. That is one of the advantages of the prototype model of OO -- you don't need to have special language constructs for many situations where ordinary OO needs such constructs since they are all subsumed under one more general set of primitives. Here we define the trait MakeProto (again, traits are not a special language feature of proto but are just a way of using it): MakeProto <- proto( new = function(., ...) { .$proto(expr = if ( !is.null(d1) ) d3 <- d1 + d2, ...) }, d1 = NULL, d2 = 5, d3 = NULL ) oo <- MakeProto$new() oo$d1 # NULL oo$d2 # 5 oo$d3 # NULL oo2 <- MakeProto$new(d1 = 7) oo2$d1 # 7 oo2$d2 # 5 oo2$d3 # 12 In the above oo$d1, oo$d2, oo$d3 are actually located in MakeProto and delegated to oo so that when one writes oo$d2 it looks into MakeProto since it cannot find d2 in oo. oo2$d2 is also not in oo2 but delegated from MakeProto; however, oo2$d1 and oo2$d3 are located in oo2 itself. That is due to the way we set it up and we could have set it up differently. Try str(MakeProto); str(oo); str(oo2) to see this. -- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com ______________________________________________ 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.