From: Martin DeMello Date: 2005-03-19T01:34:53+09:00 Subject: Re: [EVALUATION] - E03 - jamLang Evaluation Case Applied to Ruby Ilias Lazaridis wrote: > > The above thread showed finally the need to split the evaluation down > into smaller chunks. > > Here is a simple evaluation template (first part) which can be applied > to the Ruby language: > > http://lazaridis.com/case/lang/index.html Okay, that's a neat bit of work. Here's a quick solution (ruby makes most of this fairly trivial): # here's your basic talker class class Talker def sayHello puts "Hello world" end end # __FILE__ == $0 means that the program is being run directly # rather than 'require'd from another file if __FILE__ == $0 talker = Talker.new talker.sayHello end # one-pass interpreter, and you can reopen classes # so let's just continue # here are the two instance variables added to the class, complete with # autogenerated getters and setters class Talker attr_accessor :name, :age def initialize(name, age) @name, @age = name, age end # following the spec, though say_name is more rubyish def sayYourName puts @name end def sayYourAge puts @age end end # now note that our object 'talker' has access to the new methods in its # class if __FILE__ == $0 # note that we aren't breaking encapsulation and accessing the vars directly; # the setter methods are called name= and age=, and the getters are called # name and age talker.name = "Just another talker" talker.age = 1 talker.sayYourName talker.sayYourAge end # reflection class Talker # simple def sayYourClassName puts self.class.name # the 'self' is optional here end # objects know nothing about the variables that are bound to them # (a variable name is not the name of the instance anyway). The # closest you can come to the "name" of an object is it's object id, so... def sayYourInstanceName puts object_id # again, you could say self.object_id if you prefer end # advanced # caller returns a stack (array) of strings of the form # file:linenumber in `method' # so we extract the most recent one and parse the method name out # code from PLEAC def thisMethodName caller[0] =~ /in `([^']+)'/ ? $1 : '(anonymous)'; end # string interpolation in action - the bit between the #{} can be # any valid expression; to_s will be called on the result and # interpolated into the string def sayHelloAdvanced puts "#{thisMethodName}: Hello World" end # expert def sayYourClassDefinition puts "Class:" sayYourClassName # %{} is another way to write a string literal # (looks neat for multiline strings) # we use the standard 'inspect' method to print out arrays of # method names in a ["meth1", "meth2", ...] format puts %{ Methods: public: #{public_methods.inspect} protected #{protected_methods.inspect} private: #{private_methods.inspect} non-inherited: #{(methods - self.class.superclass.instance_methods).inspect} Instance Variables: #{instance_variables.inspect} } # note that the instance variables belong to the *instance*, not # to the class, so they're not technically part of the class # definition. the following code is illustrative: # # class A # attr_accessor :foo, :bar # defines getters and setters # end # # a = A.new # p a.instance_variables # => [] # a.foo = 10 # p a.instance_variables # => ["@foo"] # b = A.new # p b.instance_variables # => [] end def sayYourClassCode puts "Sadly, you cannot introspect the source code from within a program" # though see http://rubyforge.org/projects/parsetree/ # for a way to get at the parsed AST end end # testing it out if __FILE__ == $0 talker.sayHelloAdvanced talker.sayYourClassName talker.sayYourClassDefinition talker.sayYourClassCode end Hope this helps. martin