Typical/idiomatic examples of dynamic code generation with Ruby?

I

Iwan van der Kleyn

Hi there,

I'm writing a paper on the "rediscovery of dynamic languages".
Definition issues aside (what *is* a "dynamic" language, anyway?), in
it I try to show how "old" (Smalltalk, Lisp) and "new" (Python, Ruby)
programming languages are vastly superior for the cost-effective
development of scalable and secure applications compared with static
languages like C/C++ and half-breeds like Java and C#. Nothing
original for sure, but then I again I'm trying to postulate some
convincing arguments for a non-geek, managerial audience.

In the paper I'm comparing "idiomatic" examples of how these languages
deal with common problems. Problem is, I'm quite new with Ruby and I'm
a bit at a loss for examples on how to show Ruby's strengths with
dynamic code generation (metaprogramming). That is often mentioned as
one of Ruby's strengths. Don't get me wrong, I've found that Ruby has
got the necesarry nuts and bolts but I couldn't really figure out what I
could do with it, what I could not easily do with Python as well.

So my question: do you know of any examples on the subject of dynamic
code generation which would be typical for Ruby and could not be
easily implemented in languages like Python?


Regards,

Iwan
 
M

Michael Neumann

Iwan said:
Hi there,

I'm writing a paper on the "rediscovery of dynamic languages".
Definition issues aside (what *is* a "dynamic" language, anyway?), in
it I try to show how "old" (Smalltalk, Lisp) and "new" (Python, Ruby)
programming languages are vastly superior for the cost-effective
development of scalable and secure applications compared with static
languages like C/C++ and half-breeds like Java and C#. Nothing
original for sure, but then I again I'm trying to postulate some
convincing arguments for a non-geek, managerial audience.

In the paper I'm comparing "idiomatic" examples of how these languages
deal with common problems. Problem is, I'm quite new with Ruby and I'm
a bit at a loss for examples on how to show Ruby's strengths with
dynamic code generation (metaprogramming). That is often mentioned as
one of Ruby's strengths. Don't get me wrong, I've found that Ruby has
got the necesarry nuts and bolts but I couldn't really figure out what I
could do with it, what I could not easily do with Python as well.

So my question: do you know of any examples on the subject of dynamic
code generation which would be typical for Ruby and could not be
easily implemented in languages like Python?

I think stuff like "attr_accessor" is typical for Ruby. It could be
implemented like this:

class Module
def attr_accessor(*attrs)
attrs.each do |attribute|
class_eval "def #{ attribute }() @#{ attribute } end"
class_eval "def #{ attribute }=(val) @#{ attribute } = val end"
end
end
end

# and use it

class MyClass
attr_accessor :a
def initialize
@a = "test"
end
end

m = MyClass.new
p m.a # => "test"
m.a = 2
p m.a # => 2

You can do the same for defining abstract methods:

class Module
def abstract(*meths)
meths.each do |meth|
class_eval "def #{ meth }(*args, &block) raise 'abstract
method' end"
end
end
end

And for much more else. Have a look at ActiveRecords, which uses quite a
lot of metaprogramming, I guess.

Regards,

Michael
 
G

gabriele renzi

Michael Neumann ha scritto:

I'm not sure samples in ruby would be hard in python and viceversa, but
there are different idioms. Maybe ruby has some more runtime hooks like
Class#inherited or Module#included. I /think/ that a good example could
be the Interface pkg (java style check for interfaces)
http://raa.ruby-lang.org/project/interface/

Toghether with the just named keyword-like class methods there is the
class generation at runtime idiom, a built-in example is the Struct
class, and a really nice one is Test::Unit::Mock, see a sample on this
page: http://www.deveiate.org/code/Test-Unit-Mock/index.html

Another thing is the usual relying on method_missing tricks, for wich I
guess the best example is the Criteria library (wich happen to generate
sql instead of ruby, so not really metaprogramming I think :) look at:
http://mephle.org/Criteria/

It seem that your paper will be very interesting.. I even wonder how
static languages handle this situations.

just my 0.02 euro
 
I

Iwan van der Kleyn

Thanks for the tips. Today I got the Pickaxe (2004 edition) and I found
the relevant references. I'll be playing around with it for a while. In
the paper I'm comparing SQLObject (Python object-relational mapper,
kind like ActiveRecords I guess) which uses lots of metaclass wizzardry.
Although you would be able to something similar in Java, it would be far
less natural or easy to the enduser (programmer) and it would be
absolutely hell to implement. I'm hoping to come with some nice examples.

Look in Google for some nice references when searching for "Java dynamic
code generation". The way to do this in Java would be through "regular"
code generation though, which would be generated by a special tool like
XDoclet at compile time.
It seem that your paper will be very interesting.. I even wonder how
static languages handle this situations.

With luck it will be released under an Open Conent license in January.

Thanks again,

Iwan
 
J

James Edward Gray II

So my question: do you know of any examples on the subject of dynamic
code generation which would be typical for Ruby and could not be
easily implemented in languages like Python?

I don't know if this is the kind of thing you're after and I don't know
Python, so I have no idea how it compares, but and interesting example
did come up in my project today.

I'm building a server. When some event happens in the server, it
notifies monitoring code with an Event object. My first crack at that
class looked like:

class Event
CONNECT = "Connect"
LOGIN = "Login"
COMMAND = "Command"
DISCONNECT = "Disconnect"

def initialize( connection, identity,
type, details = nil, time = Time.now )
@connection = connection
@identity = identity

@type = type
@details = details
@time = time
end

attr_reader :connection, :identity, :type, :details, :time

def connect?() @type == CONNECT end
def login?() @type == LOGIN end
def command?() @type == COMMAND end
def disconnect?() @type == DISCONNECT end
end

That worked, of course. However, one of my major goals with this
server is to keep it very open to change. I know for a fact it will be
modified after deployment, so I'm planning ahead.

The problem with the above version comes when I add a new event type.
I provide those little helper methods like command?(), to keep you from
having to write:

if event.type == Event::COMMAND
# ...

# can be written as...

if event.command?
# ...

However, when I decide I need a new event type, I have to add another
constant and a new helper method. That goes against DRY philosophy.
So, I changed the class to:

class Event
CONNECT = "Connect"
LOGIN = "Login"
COMMAND = "Command"
DISCONNECT = "Disconnect"

def initialize( connection, identity,
type, details = nil, time = Time.now )
@connection = connection
@identity = identity

@type = type
@details = details
@time = time
end

attr_reader :connection, :identity, :type, :details, :time

constants.each do |e|
value = const_get e
define_method((e.downcase + "?").to_sym) do
@type == value
end
end
end

Problem solved. Helper methods are now auto-generated from class
constants. Add a new constant, get a new helper method.

Hopefully, that's the kind of thing you are looking for. Good luck
with your paper.

James Edward Gray II
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top