Is Dwemthy's Array possible in smalltalk?

Darren Hobbs darren.hobbs at gmail.com
Thu May 12 16:54:14 UTC 2005


There's a very interesting article here about metaprogramming in Ruby: 
http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

The final section is titled Dwemthy's Array and links to the original code 
here: http://poignantguide.net/dwemthy/

I've inlined the most interesting code from that page below. 

In a nutshell what it does is dynamically add fields to subclasses of the 
Creature class. The 'traits' line about halfway down says call the class 
method 'traits' passing a array of symbols.
Creature.traits is a class method. @traits is an instance variable I think, 
my Ruby isn't that great and the fact that it's being accessed from a class 
method is confusing me..

My question is, is this kind of metaprogramming possible in Smalltalk?

Regards,

-Darren

# The guts of life force within Dwemthy's Array
class Creature
# Advanced metaprogramming code for nice, clean traits
def Creature.traits( *arr )
return @traits if arr.empty?
attr_accessor *arr
arr.each do |a|
class_eval %{
class << self
def #{a}( val )
@traits ||= {}
@traits[#{a.inspect}] = val
end
end
}
end
class_eval %{
def initialize
self.class.traits.each do |k,v|
instance_variable_set( "@" + k.id2name, v )
end
end
}
end

# Creature attributes are read-only
traits :life, :strength, :charisma, :weapon

# This method applies a hit taken during a fight.
def hit( damage )
p_up = rand( charisma )
if p_up % 9 == 7
p_up /= 4
puts "[#{ self.class } magick powers up #{ p_up }!]"
end 
@life -= damage
puts "[#{ self.class } has died.]" if @life <= 0
end

# This method takes one turn in a fight.
def fight( enemy, weapon )
if life <= 0
puts "[#{ self.class } is too dead to fight!]"
return
end

# Attack the opponent
your_hit = rand( strength + weapon )
puts "[You hit with #{ your_hit } points of damage!]"
enemy.hit( your_hit )

# Retaliation
p enemy
if enemy.life > 0
enemy_hit = rand( enemy.strength + enemy.weapon )
puts "[Your enemy hit with #{ enemy_hit } points of damage!]"
self.hit( enemy_hit )
end
end

end

class DwemthysArray < Array
alias _inspect inspect
def inspect; "#<#{ self.class }#{ _inspect }>"; end
def method_missing( meth, *args )
answer = first.send( meth, *args )
if first.life <= 0
shift
if empty?
puts "[Whoa. You decimated Dwemthy's Array!]"
else
puts "[Get ready. #{ first.class } has emerged.]"
end
end
answer || 0
end
end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20050512/cb5078b6/attachment.htm


More information about the Squeak-dev mailing list