On Tue, Feb 06, 2007 at 07:33:20AM +0900, dblack / wobblini.net wrote: > > p1 = Proc.new { |x=nil,y=nil| ... } # accept 2 or fewer args > > p2 = Proc.new { |x, y, *z| ... } # accept 2 or more args > > p3 = Proc.new { |*x| ... } # no more single-arg special case! > > > >That is, use the same argument list handling for a 'def' method > >definition, > >a block, and a Proc/proc/lambda. > > I think the reason for there not being default arguments in code > blocks is the ambiguity of the pipe character: > > {| x=1 | 2 | 3 } # {(x=1) 2 | 3 } or {(x=1|2) 3 } ? > > Dave Thomas suggested something at RubyConf 2005 along the lines of: > > def m(a,b,c) # method > end > > def (a,b,c) # anonymous function > end > > I'm not sure what happened to that; I haven't seen it mentioned much > in discussions of this stuff. But make this into block syntax and you still have potential ambiguities: 3.times { (i=nil) puts i } 3.times do (i=nil) puts i end (i=nil) is a valid expression/statement in its own right, so you'd need some more lexical rules to disambiguate this from an argument list. I'd hate more whitespace-sensitive rules to be added, e.g. {(i) ... } # block args { (i) ... } # expression :-( Perhaps you use parentheses, and if a block starts with an open-parenthesis then it's always an argument list. If you want it otherwise, you have to explicitly avoid it: 3.times { nil, (a=b, c=d) } It seems the rest of the ASCII set has been used already; e.g. angle-brackets would have the same problem. 3.times { < i = j > 4 > puts i } Incidentally, I do see a reason for not doing full argument-checking in blocks: there are methods which pass block arguments which it's convenient for the block to ignore if it doesn't want them. 3.times { puts "hello" } 3.times { |x| puts "hello #{x}" } You could get around this by: (a) having different methods which pass or do not pass arguments: 3.times { puts "hello" } 3.times_i { |x| puts "hello #{x}" } (b) making such arguments explicitly ignorable at the caller side, which I think I prefer. At worst: class Integer def times(&blk) if blk.arity == 1 ... loop, yield with index else ... loop, yield without index end end end Regards, Brian.