On Tue, 1 Nov 2005, NAKAMURA, Hiroshi wrote:

> Agreed.  What do you think about adding the following snippet to csv.rb?  No
> need to Symbol support?
>
> Regards,
> // NaHi
>
> class CSV
>  class Table
>    def Table.parse(str_or_readable, fs = nil, rs = nil, &block)
>      create.parse(str_or_readable, fs, rs, &block)
>    end
>
>    def Table.create(*field)
>      new(field)
>    end
>
>    def parse(str_or_readable, fs = nil, rs = nil, &block)
>      begin
>        reader = CSV::Reader.create(str_or_readable, fs, rs)
>        if @field.nil?
>          @field = reader.shift
>        end
>        if block_given?
>          reader.each do |row|
>            yield(NamedRow.new(@field, row))
>          end
>          nil
>        else
>          reader.collect { |row|
>            NamedRow.new(@field, row)
>          }
>        end
>      ensure
>        if reader
>          reader.close
>        end
>      end
>    end
>
>    class << self
>      private :new
>    end
>
>    def initialize(field)
>      @field = field.empty? ? nil : field
>    end
>
>    class NamedRow < Array
>      def initialize(field, row)
>        super(row)
>        @field = field.map { |name|
>          name.to_s
>        }
>      end
>
>      def [](name)
>        if name.respond_to?(:id2name)
>          name = name.id2name
>        end
>        if @field.include?(name)
>          super(@field.index(name))
>        else
>          super
>        end
>      end
>    end
>  end
> end

i think that would adequate.  two comments

   - i'm hugely in favour of keyword style interfaces like

       def parse(str_or_readable, opts = {}, &block)
         fs = opts.values_at('fs', :fs).first
         rs = opts.values_at('rs', :rs).first

     vs.

       def parse(str_or_readable, fs = nil, rs = nil, &block)

     because it makes it much more possible to add functionality without
     breaking the interface later, eg:

       def parse(str_or_readable, opts = {}, &block)
         fs = opts.values_at('fs', :fs).first
         rs = opts.values_at('rs', :rs).first
         strict = opts.values_at('strict', :strict).first

     and because i personally find

       parse io, true, false

     slight obtuse to read, espcially as the number of optional paramters
     increases.

   - i do agree that the most light-weight field naming scheme, think that one
     might be too light-weight.  i have found that having named fields leads
     naturally to wanting to write code such as

       name, ssn, age = row.values_at 'name', 'ssn', 'age'

       row.update 'name' => 'matz', 'age' => '?'

     so something a bit more capable than simply overriding [] may be in order.
     i would at the absolute bare minimum expect to be able to write

       row['name'] = 'axel'

     since being able to say

       p row['name']

     without also being able so set by field name seems an obvious violation of
     (my) POLS

     and arrayfields has already done the heavy lifting here - though one could
     certainly re-write some of it for a slightly lighter weight approach -
     though it's plenty light weight imho.

regards.

-a
-- 
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| anything that contradicts experience and logic should be abandoned.
| -- h.h. the 14th dalai lama
===============================================================================