From: Brian Candler Date: 2003-04-25T05:44:26+09:00 Subject: Re: How to call an object instance's method? On Fri, Apr 25, 2003 at 03:44:31AM +0900, Yukihiro Matsumoto wrote: > It's bad for who don't care white spaces. Care what you write. > "puts( 3 )" and "puts (3)" are _not_ same. > > "puts (a+b).abs" as "(puts(a+b)).abs" really made me mad. Yes, that I can sympathise with. It upsets poetry mode if the first character after a method call is an opening parenthesis, but you were only using it to group terms in one method argument. I think we have a new gotcha, which replaces an old one. The old gotcha: puts (a+b).abs \=> both treated puts(a+b).abs / as (puts(a+b)).abs !! The new gotcha: sin(a) + b => (sin(a)) + b sin (a) + b => treated as sin( a+b ) !! puts(a+b).abs => still treated as (puts(a+b).abs) !! The new gotcha might catch you out less often, but I think only if you're aware of it already, and you are careful with the space bar. Deep down something tells me "the first case is more consistent! It's less surprising!" I think the fundamental problem is that parentheses are being used for two different functions: 1. as an *optional* grouping of arguments to a method 2. to group terms within an expression, e.g. to override operator precedence IIUC, the old rule was that an opening parenthesis was always taken as case (1). Now it's case (1) if there is no space, or case (2) if there is a space. I expect it would be too radical to suggest that a different symbol be used for case (1), grouping arguments - e.g. sin |a| + b Thinking aloud here. Consider methods which take only one parameter: foo x foo (x) foo(x) These can all be treated the same; it doesn't matter in this case whether the parentheses are part of the expression, or the argument list. Now, introduce another term, how is it grouped? foo x + y # method foo, argument x + y foo(x) + y # method foo, argument x That's fine, but alternatively we could consider the second case as foo((x) + y) # method foo, argument (x) + y The first case is probably what you expect for sin(a)+b the second case is what you expect for puts (3).class You *could* make the second case the default, but that would annoy mathematicians, who would have to start writing their code like this: (sin a) + b # instead of sin(a) + b Let's assume we are happy to annoy mathematicians for the moment. For a single argument, we could say "parentheses are always part of an expression" (case 2 above), and resolve foo (x) + y as foo( (x)+y ) Now, suppose foo takes two arguments? What to do with foo(x,z) + y We could always outlaw that in favour of (foo x,z) + y but if the parser were clever enough to note that a comma cannot be used within an expression, it could realise that foo (x,z) + y must really mean (foo (x),(z)) + y In fact with a comma I think there is no ambiguity: puts ("hello","world").class can only be interpreted in one possible way. So maybe we should insist that all methods take at least two arguments :-)) Hmm, don't think I'm really getting anywhere here - except I think I understand a bit better where the problem arises. I can probably talk myself into the current solution. Poetry mode generally *requires* a space between the method and its argument, simply to separate the tokens, as in puts x.class So you can argue that "puts (x).class" is poetry in the same way, whereas "puts(x).class" has an argument list (x) for puts. It still doesn't sit comfortably with me though. Cheers, Brian.