On Sun, 2004-09-26 at 08:32, Brian Candler wrote:
> On Sun, Sep 26, 2004 at 04:19:55AM +0900, Markus wrote:
> > > (3) It may be possible to keep Ruby's automagic exploding of arguments, if
> > > we limit it to cases where there is no ambiguity. I am thinking of:
> > > 
> > >   - the sender passes a single array value;
> > >   - the receiver REQUIRES two or more arguments.
> > > 
> > > This is unlike def foo(head,*rest) or proc {|head,*rest| ... }, where it can
> > > take _one_ or more arguments, so the rule would not apply.
> ...
> >      I played around with this idea (briefly) yesterday before posting. 
> > I reached the (tentative) conclusion that any attempt to retain
> > auto-explosion and enforce consistency would blow up.  The goatch for
> > this one: if a method required two arguments and was passed an array by
> > some user, changing the method so that the second argument was optional
> > would (instead of required) would silently change what was passed in for
> > the second argument--it would now get the array, and the second would
> > get the default.
> 
> True, but if you change the number of parameters which a (method|proc|block)
> expects, then you're almost certain to change the semantics anyway.

     No.  Consider: you have something (in working code) that accepts
two parameters, and every time it is called, it receives two
parameters.  The code, as written, has been well tested and is known to
work.  
     If you add a default value to the second parameter, for use by 
newly written code, you would expect the old code (which always provides
two values) to continue to function correctly.  It would, under 1.8.0,
and any other language I can think of that allows for default
parameters.

     But if some users were depending on auto-array-explosion under the
semantics proposed above, the old code would silently break; the array
that had auto-expanded when there were two REQUIRED parameters would
quietly stop exploding.

> In the case I'm thinking of, Ruby would otherwise have raised an
> "ArgumentError: wrong number of arguments (1 for 2)". So you're still
> changing the semantics by making the second argument optional.

     No, under your proposed semantics it would have otherwise
auto-exploded because:
> > >   - the sender passes a single array value;
> > >   - the receiver REQUIRES two or more arguments.


> Somehow I feel happier retaining this for blocks, for backwards-
> compatibility with 1.8.x, than to introduce it for method calls for
> consistency:
>
>   def foo(a,b)
>     # ...
>   end
> 
>   a = [1,2]
>   foo(a)      # Feels like this *ought* still to raise an ArgumentError

     I agree.


> How do people feel about
> 
>   myhash.each{|key,value| ... }
> 
> raising an ArgumentError, forcing you to rewrite it as
> 
>   myhash.each{|(key,value)| ... }

     My present thinking is that this is a red herring.  We've been
talking as if Hash#each perforce uses default auto array explosion,
assuming that it is internally analogous to:

    yield(kv_array) 

         ... { |kv| ...
         ... { |k,v| ...

and thus

    kv  = kv_array
    k,v = kv_array

where the latter case requires auto array explosion.

     But:

     1. As people have previously pointed out, there is no actual
        kv_array; it should, if anything, be a new class (an
        Association) 
     2. Since the array supposedly being exploded is inside the
        definition of Hash#each, it would only have to be changed in
        this one place (by adding an "*") to make it explicit in any
        case. 
     3. What's really going on is auto IMPLOSION, analogous to:
        
            yield(k0,v0) 
        
                 ... { |kv| ...
                 ... { |k,v| ...
        
        and thus
        
            kv  = k0,v0
            k,v = k0,v0
        
        ...all of which would work exactly as before, even if
        auto-explosion was completely eradicated from the language. 
        (Auto implosion appears to be much less problematic since there
        is only one mechanism that I am aware of to pass around lvalue
        lists, and no l-side "default destination" analog to default
        rvalues).
        
        
-- Markus