Re: [ANN] Article: An Exercise in Metaprogramming with Ruby



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


.



Relevant Pages

  • Re: Reorder a XML file by distance from a location
    ... If you tell me how to sort alphabetically, or by latitude or ... longitude, I would be very happy already. ... def ... distance other.distance ...
    (comp.lang.ruby)
  • Re: NMEA , request for real live sample
    ... class NMEAHandler ... def rmc(time, latitude, longitude, speed, course, magnetic_variation) ...
    (comp.lang.ruby)
  • Re: Trying to convert from Latitude/Longitude to Radar plot?
    ... RF strength data. ... For simplicity, I will designate latitude and longitudes as. ... Suppose the original coordinates are in A and B (longitude) ... > I have taken a series of RF field strength measurements of an FM ...
    (microsoft.public.excel.charting)
  • Re: Conversions
    ... the North and East coordinates would have to be ... projected from latitude and longitude for them to have a conversion back to ... point to be rotated and where the RotatedDirection is the calulated ...
    (sci.geo.satellite-nav)
  • Re: estimating error in my GPS position.
    ... longitude coordinate and convert them to meters. ... longitude and latitude data respectively. ... The manual says the GPS is good to within 30m but this is for the ... on the surface of the ocean. ...
    (sci.geo.satellite-nav)

Loading