From: Rob Biedenharn Date: 2011-11-01T06:43:53+09:00 Subject: Re: Newbie Ruby Softball On Oct 29, 2011, at 3:00 AM, Eric Christopherson wrote: > On Fri, Oct 28, 2011 at 9:47 PM, mike lev > wrote: >> I'm new to ruby but trying to learn. I've been trying to figure out >> some >> things about a book example and having the darndest time of it. I've >> been trying to google and look up the api and use a book reference >> but >> I'm left with some questions. That's where I was hoping a kind soul >> from >> this forum could come in. Answers directly below, code on bottom. >> >> I understand that @varname is essentially defining how open the >> variable >> "varname" is, but I don't understand why "@children = children" is >> needed, couldn't the code just use "children"? > > See below. > >> >> children and node_name reference attr_accessor. Am I right to think >> that >> the names of these two objects are inconsequential? What are we doing >> here? I'm guessing making instances of attr_accessor and naming them >> "children" and "node_name"? >> >> Does children have the "each" parameter by virtue of inheriting from >> attr_accessor? Is each something I can do on each and every object >> then? >> >> thanks for bearing with me! >> >> >> >> class Tree >> attr_accessor :children, :node_name > > attr_accessor is a method, not a class; and :children and :node_name > are parameters passed to it; not instances of it. Since they start > with colons, they are symbols -- which are like strings in many ways. > Usually they are used in Ruby to refer to something in a literal way; > here we're not trying to get the value of variables or methods called > children and node_name -- we're trying to use the literal names. > > attr_accessor, then, takes one or more names (which can be symbols or > strings) and generates methods from them on the fly. These methods are > accessors -- they allow outside code to access instance variables. > > The names are only consequential in that you have to refer to them by > the names you give them. > >> >> def initialize (name, children=[]) >> @children = children >> @node_name = name >> end > > Here, name and children (without the @) are parameters to the method > initialize; when they come into the method they become local > variables. So nothing outside of the initialize method can see them. > > When we assign them to @-prefixed variables, those are instance > variables, which can be accessed anywhere in the class (and, since we > defined accessors for them, outside of the class too). > > Note that the name of the instance variable doesn't have to be exactly > the name of the parameter but with @ prefixed -- here the instance > variable @node_name corresponds to the parameter name, instead of > node_name. > >> >> def visit_all(&block) >> visit &block >> children.each {|c| c.visit_all &block} >> end > > children here should be @children; just plain children is a local > variable, which isn't defined in visit_all. No, in this case the plain children is the method created by the attr_accessor and that line is effectively the same as: self.children.each {|c| c.visit_all &block} It is precisely because it is not yet seen as a local variable that it is treated as a method to be called and why a misspelt name often gives an error like: NameError: undefined local variable or method `chldren' for # -Rob > > @children supports the each method because it's an array -- or at > least it's expected to be. Since Ruby is dynamically typed, you could > make @children any sort of object. Mainly collection-like types (e.g. > arrays, hashes, etc.; or user-defined collection types) support the > each method. > >> >> >> def visit(&block) >> block.call self >> end >> end >> >> ruby_tree = Tree.new( "Ruby", [Tree.new("Reia"), >> Tree.new("MacRuby")]) >> >> puts "Visiting a node" >> ruby_tree.visit {|node| puts node.node_name} >> puts >> >> puts "Visiting entire tree" >> ruby_tree.visit_all {|node| puts node.node_name} > Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/