Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- From: ara.t.howard@xxxxxxxx
- Date: Sun, 26 Mar 2006 15:16:15 +0900
On Sun, 26 Mar 2006, Joel VanderWerf wrote:
The point about coupling (mentioned in the second-to-last paragraph of the
article) is important, and I feel it is dismissed to easily in the article.
There are some tradeoffs to consider, though perhaps they are out of the
scope of the article, which is intended as an exercise, not as a complete
guide:
1. Suppose your code needs to _discover_ what fields are in the file? You
can use #instance_methods(false), but that is not perfect: you have to
filter out "to_s" and "inspect", which were added by #make. And what if you
add a new method in addition to the ones generated by #make? The field names
could be stored in a list kept in class instance variable...
2. Once you have discovered the field names, you have to use send(fieldname)
and send("#{fieldname}=") to access them. That's more awkward and (at least
in the second case) less efficient than Hash#[] and #[]=. Who's the "second
class citizen" in this case?
3. If you really know the field names "in advance" (that is, you have enough
information to hard code them into your program), rather than "by
discovery", then maybe it is better to use a different metaprogramming style
in which the fields are declared using class methods:
class Person
field :name, :favorite_ice_cream, ...
end
In this way, some rudimentary error checking can be performed when reading
the file, rather than failing later when trying to serve ice cream to the
person. (I just hate it when my ruby-scripted robo-fridge serves me passion
fruit and rabbit dropping ice cream.) This is not always the best way to go
(what if, as the article points out, fields get added to the file?), but one
more thing to keep in mind.
i'm totally with you on this joel. still, i think one can have a bit of both:
harp:~ > cat a.rb
require "arrayfields"
require "csv"
csv = <<-csv
latitude,longitude,description
47.23,59.34,Omaha
32.17,39.24,New York City
73.11,48.91,Carlsbad Caverns
csv
class CSVTable < ::Array
attr "fields"
def initialize arg
CSV::parse(arg) do |row|
row.map!{|c| c.to_s}
if @fields
self << row
else
@row_class = Class::new(::Array) do
define_method("initialize") do |a|
self.fields = row
replace a
end
end
@fields = row
end
end
@fields.each{|field| column_attr field}
end
def << row
super @row_class::new(row)
end
def column_attr(ca)
singleton_class = class << self; self; end
singleton_class.module_eval{ define_method(ca){ map{|r| r[ca]}} }
end
def [](*a, &b)
m = a.first
return(send(m)) if [String, Symbol].map{|c| c === m}.any? && respond_to?(m)
super
end
end
table = CSVTable::new csv
p table
puts
p table.fields
puts
table.fields.each{|f| puts "#{ f }: #{ table[f].join(', ') }"}
puts
table.each{|row| puts row.fields.map{|f| "#{ f }: #{ row[f] }"}.join(', ') }
puts
harp:~ > ruby a.rb
[["47.23", "59.34", "Omaha"], ["32.17", "39.24", "New York City"], ["73.11", "48.91", "Carlsbad Caverns"]]
["latitude", "longitude", "description"]
latitude: 47.23, 32.17, 73.11
longitude: 59.34, 39.24, "48.91
description: Omaha, New York City, Carlsbad Caverns
latitude: 47.23, longitude: 59.34, description: Omaha
latitude: 32.17, longitude: 39.24, description: New York City
latitude: 73.11, longitude: 48.91, description: Carlsbad Caverns
regards.
-a
--
share your knowledge. it's a way to achieve immortality.
- h.h. the 14th dali lama
.
- Follow-Ups:
- Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- From: Joel VanderWerf
- Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- References:
- [ANN] Article: An Exercise in Metaprogramming with Ruby
- From: rubyhacker
- Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- From: Meinrad Recheis
- Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- From: Joel VanderWerf
- [ANN] Article: An Exercise in Metaprogramming with Ruby
- Prev by Date: Re: Best Database For Ruby
- Next by Date: Re: Best Database For Ruby
- Previous by thread: Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- Next by thread: Re: [ANN] Article: An Exercise in Metaprogramming with Ruby
- Index(es):
Relevant Pages
|
Loading