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