Hello,
I am a newbye to ruby (I looked  at the newsgroup and the web pages some
weeks ago, but did  not try to program until I  received Dave and Andy's
book last week), although I have  a long experience with many other high
and  low-level languages.  I give  here  my first  impressions before  I
forget them, in the  hope that they may interest someone  and that I may
receive some useful advice (this list seems quite friendly).

 First my  global impression  which survived translation  of some  of my
scripts is that ruby is a  perfect replacement for perl and python (when
translating  some scripts  I  had  only some  minor  annoyances; on  the
other  hand I  could achieve  some substantial  improvements due  to the
higher-level nature of ruby). Some of the minor annoyances were:

  - I had trouble using sort! in method-chaining because

    irb(main):006:0> [1,2].sort!
    [1, 2]
    irb(main):007:0> [1].sort!
    nil

    the reason why sort! does not return its result for arrays of length
    1 eludes me.

  - In perl, if one wants to sort according to several criteria, one can
    write something like that

      sort { length($a) <=> length($b) or $a cmp $b }

    this does not work in ruby since 'or' behaves completely different --
    it can apparently be used only in a very restricted way in boolean
    expressions. The closest I could come with is:

      sort {|a,b|  [a.length,a]<=>[b.length,b]}

    but  it does  not have  the same  effect as  the perl  idiom not  to
    evaluate the second sort criterion when the first suffices.

  - I was very surprised that  each_pair is not defined for arrays, only
    hashes. Of course you can roll your own:

     class Array  
       def each_pair 
         each_index do |i| yield(i,self[i]) end
       end 
     end

    but why is such an essential idiom not pre-defined?

  - I  have some problems with  scopes. In particular, that  one can not
  define local functions.  The closest I could come with  is to define a
  local Proc object and use .call on it. Is that the recommended way?

 The main reason I looked at ruby is that I had very high hopes for this
language: my job is mathematics and  I thought ruby might be well suited
for that.  Mathematical programming involves  defining all the  time new
mathematical objects and  programming usual and not  so usual operations
on  them. As  an exercise  to test  ruby for  that purpose,  I tried  to
program fractions  and multivariate polynomials.  I found along  the way
what I  perceive as a  defect in ruby  (lack of overloading),  but other
people including matz may have another view which would interest me.

  To start with my example I started with:

class Frac
  attr_accessor(:num, :den)
  def initialize(n,d=1)
    @num,@den=n,d
    simpl!
  end
  def simpl!
    g=@num.gcd(@den)
    @num/=g
    @den/=g
  end
  def to_s
    res=@num.to_s
    res+="/"+@den.to_s unless @den==1
    res
  end
  def +(other)
    Frac.new(@num*other.den+@den*other.num,@den*other.den)
  end
  def -(other)
    Frac.new(@num*other.den-@den*other.num,@den*other.den)
  end
  def *(other)
    Frac.new(@num*other.num,@den*other.den)
  end
  def /(other)
    Frac.new(@num*other.den,@den*other.num)
  end
end

Remark that I do  not derive Frac from Numeric, since I  want it to work
for an arbitrary  Euclidean base ring. Also I just  assume that the base
ring has  a method  for gcd defined.  If one wants  to use  fractions of
integers, one can write

class Integer
  def gcd(b)
    a=self
    while b!=0
      a,b=b,a.modulo(b)
    end
    a
  end
end

Now the code above works fine as long as I work only with Fracs. Suppose
now that I want to define the addition of a Frac and an integer:

  Frac.new(1,3)+2

In a language like C++, I would  use overloading to add a new method for
operator  + when  the  argument is  not  a  Frac. But,  and  this is  my
perceived  deficiency,  it  seems  that  ruby has  no  such  concept  as
overloading.  For  the moment,  a  possible  technique  is to  define  a
conversion function:

def Frac(a)
  if a.type==Frac
    a
  else 
    Frac.new(a,1)
  end
end

[ by the way here is a minor gripe: I first wrote the above, envisioning the
  possibility in the future of more cases, as:

  case a.type
    when Frac
      a
    else
      Frac.new(a,1)
  end

  but this does not work, apparently because === is not defined for Class]
   
and use the conversion function to change my definitions to:

  def +(other)
    other=Frac(other)
    Frac.new(@num*other.den+@den*other.num,@den*other.den)
  end

But the call to Frac() is probably more overhead than kernel dispatching
by an overload mechanism. And, now, what about the other direction, i.e.:

  2+Frac.new(1,3)

Here one  is really  at a  loss without  overloading: the  only possible
thing to do is to redefine the method + for integers!
 At that stage, I thought I would  have to abandon ruby for my purposes.
However I noticed in  the book the mention of a  library 'Complex' and I
thought I would have a look. Well, miracle,

   2+Complex(1,3)

works!  This apparently  uses a  mechanism for  which I  could not  find
non-Japanese documention, involving 'coerce'. If I mimic what I found in
'Complex', that is add:

  def coerce(other)
    [Frac.new(other), self]
  end

now my example  works. I would like a clear  explanation of exactly what
is the mechanism here. It seems to me that the method + for integers has
a pre-defined hook  to look for coerce  for an unknown type.  It is also
probably to provide a similar hook  for future additions that in Complex
one has:

  def + (other)
    if other.kind_of?(Complex)
      re = @real + other.real
      im = @image + other.image
      Complex(re, im)
    elsif Complex.generic?(other)
      Complex(@real + other, @image)
    else
      x , y = other.coerce(self)
      x + y
    end
  end

but I feel:
  -the above code is complicated, and clumsy, compared to overloading
  -contrary  to  overloading,  there  is no  possibility  to  extend  an
  already-existing method  for an already-existing  type if no  hook has
  been provided.

This  last point  bothers me:  it  is very  nice  that in  ruby one  can
dynamically add  to a class,  by reopening it.  Overloading is a  way to
'reopen'  a method,  and the  possibility to  reopen a  class is  not so
useful without it

 Ok, now what did I miss, and  what is the rationale for no overloading,
or the replacement for it that I missed?

P.S. Before people  point it to me,  I just noticed that  in the library
there is  a rational.rb with code  similar to the one  I outlined above,
excepted more complicated at places for reasons which elude me.