On Fri, Mar 28, 2003 at 07:02:09AM +0900, Han Holl wrote:
> The problem I'm having is in the case insensitive case: it's somehow
> asymmetrical: while to_i return an integer, to_s does  _not_ return a
> String but an Awk (as does downcase).
> This means I can't use
>    downcase <=> other.downcase
> as I's like to. Is it possible to use some variation of super ?

Seems unlikely, since 'downcase' returns a different object; <=> is an
instance method so it needs to operate on 'self'

Personally I've become very sold on 'has_a' rather than 'is_a'
relationships. Taking this approach literally in your case gives:

  require 'delegate'
  class Awk < DelegateClass(String)
    include Comparable
    @@intpattern = /^\s*[-+]?\d+$/
    @@casesensitive = false
  
    def self.casesensitive(val)
      @@casesensitive = val
    end
  
    def initialize(str)
      super(str)
    end
  
    def <=>(other)
      if @@intpattern =~ to_s && @@intpattern =~ other.to_s
        to_i <=> other.to_i
      elsif @@casesensitive
        to_s <=> other.to_s
      else
        to_s.downcase <=> other.to_s.downcase
      end
    end  
  end

However, I can certainly see why you'd want to subclass String in this
example: it just seems the obvious thing to do, and you might be concerned
about the overhead of delegation.

But in general, I find that having an instance variable (it's "@obj" in the
above example) even for a simple wrapper class that just adds a couple of
methods and delegates everything else can actually be extremely useful. It
allows your wrapper to take on the characteristics of @obj whatever it is,
rather than being restricted to String (say).

A similar result - adding a few methods and leaving everything else
unchanged - can be obtained with singleton classes. How about this approach:

  module Awk
    @@intpattern = /^\s*[-+]?\d+$/
    @@casesensitive = false
  
    def self.casesensitive(val)
      @@casesensitive = val
    end
  
    def <=>(other)
      if @@intpattern =~ to_s && @@intpattern =~ other.to_s
        to_i <=> other.to_i
      elsif @@casesensitive
        to_s <=> other.to_s
      else
        to_s.downcase <=> other.to_s.downcase
      end
    end
    def ==(other)
      (self <=> other) == 0
    end
  end
  
  a = 'a'
  a.extend Awk
  b = 'A'
  b.extend Awk
  
  if a == b
    puts 'equal'
  end
  a = '21'.extend Awk
  b = '3'.extend Awk
  if a > b
    puts "OK"
  end

That looks pretty neat to me...

Regards,

Brian.