You wrote:
> Hello,

Hello too, :-)

(...)

> 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.

sort! returns 'nil' if the list was not necessary to be sorted. A list
with only one element cannot be sorted sensefully, hence the
'nil'.

Perhaps that effect of sort! will be changed in future (if my
interpretation of past discussions is right). 

>   - 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 }

In Ruby only 'nil' and 'false' are false. All other are true; so also
the value zero! But there is a method Numeric#nonzero? that returns
'nil' if the receiver was zero, otherwise it returns the receiver. You
can use it to write the code block of sort like:

  { (a.length <=> b.length).nonzero? || a <=> b }

(...)

>   - 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 trick is here, that you are even not *able* to define a
function. *Neither* a global one *nor* a local one. You can only
define methods. Remember Ruby is fully OOL. Not a hybrid like Python
or C++.

A method, however, *ought* to belong to a certain class. If you
define a method on toplevel outside of every class definition, that
method belongs to class Object and will become a private instance
method of it. As such, it is visible on all places in your code as
every class/module inherits from class Object at last!

So it seems you define a function but in reality you was fooled by
Ruby there! ;-)

So the closest to come to a local function is indeed a local Proc
object. You could use the methods Proc#call or Proc#[] to call such an
instance. Proc instances will also often used as anonymous callback
'functions'. I am sure you will like them :-)

> 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

I am not a mathematican, but I am sure it will fit your needs! But
please have also a look to the Ruby Application Archive (RAA) 

  http://www.ruby-lang.org/en/raa.html

to find some valuable modules, that may help you here for mathematical
tasks. Some among them:

 - NArray
 - BigFloat
 - NumArray
 - Polynomial

(...)

> overloading), but other people including matz may have another view
> which would interest me.

Erhm ... what? Lack of overloading? Impossible ... ah you mean
overloading by parameter type, yes? That is indeed not available in
Ruby (nor in Python or Smalltalk, BTW). The reason is that variables
are not typed in such languages. Therefore it is difficult (perhaps
impossible in some cases?) for the compiler to fiddle out on
compilation time what kind of method to be called later on!

You can think from method invocation as sending a method selector to a
certain object. Like that:

  a = 3
  b = 5
  a.send(:+, b)   # => 8

If dispatching would not be done via selector only but also by
argument type, the message lookup would slow down, IMO. First find the
*group* of messages that *could* apply, then look whether
argument-type-overloading applied or not. If not call the method; if
yes look for the one with the right argument signature!

And how to handle lookup in parents? Parent contain overloaded
methods, child only one method catching all possible types
... pfffhhh!

Or if you design a class with overloaded-on-arguments methods, how
would you prevent me to overload your methods again but this time
catching *all* possible types of arguments? Not possible? But if I
need to?

I really do not know, if a solution of all this is worth the trouble!
Not that I believe that there *is* a senseful undoubtable and backward
compatible solution that would not bite us another way around or
weaken Ruby's nice dynamic behavior ...

But there is the coerce mechanism ...

(...)

> 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:

(...)

> 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

That was exactly what I meant with the 'coerce' mechanism.

> 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

I think you have understood the coerce mechanism very well! I would
really not know what else to describe to you.

> 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

It depends. Above I have tried to show you the problems we would
struggle in if we add overloading-on-arguments to such a highly
dynamic language like Ruby. I dare to guess that there are cases where
a compiler would even not *able* to tell you what kind of object is
passed to a method right now during compilation time!

So perhaps it is still better to let the method analyze its arguments
if necessary instead of teaching the compiler to guess ...

>   -contrary to overloading, there is no possibility to extend an
>    already-existing method for an already-existing type if no hook
>    has been provided.

Not totally true! You could alias the old method and create a new one
with same name like the old one but different behavior! Like that:

  class FooNbr
    attr :n
    def initialize(n)
      @n = n
    end
    def +(other)
      self.n + other.n
    end
  end

  # Not very clever the method FooNbr#+? FooNbr.new(12)+2 wouldn't
  # work as 2+FooNbr.new(12) wouldn't work too. So let us change it!

  class FooNbr
    alias :oldplus :+
    def +(other)
      if other.type < FooNbr
        self.oldplus other
      else
        x, y = self.coerce(other)
        x + y
      end
    end
    def coerce(other)
      [self.n, other]
    end
  end

  a = FooNbr.new(12)
  b = FooNbr.new(2)
  a + b
  a + 5
  7 + b
  
You see: although the original FooNbr#+ had no coerce, we have simply
introduced it by 'reopen' the class definition and remembering and
overwriting the original FooNbr#+ method with a new one.

> 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

It is not really necessary, IMHO, as I have tried to show you above.

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

Let me thank you for your critical questions and remarks. I hope,
though, that I was able to give you some pointer/hints why you
overloading scheme would be more trouble than blessing in my opinion
at least ...

(...)


Best regards,
\cle