From: Ben Giddings Date: 2005-08-11T04:38:16+09:00 Subject: Re: new block notation On Aug 10, 2005, at 14:48, Austin Ziegler wrote: > They aren't equal, though. There is a binding difference between > do..end and {}. > > foo bar { baz } # same as: foo(bar { baz }) > foo bar do baz end # same as: foo(bar) { baz } > > The difference in binding *is* useful, I think, as it does allow for > cleaner poetry mode: > > task :tar do |t| > # ... > end > > Whatever solution involving blocks would have to make this binding > difference easy and clean, the way that it is now. Right. I kinda knew this when I posted (at least, I remembered something about them being subtly different). I don't know that this is a good thing though. In the above example, using {} gives a syntax error because :tar isn't a method, and can't accept a block. I think what would be worse is: irb(main):018:0> def foo irb(main):019:1> if block_given? irb(main):020:2> yield self irb(main):021:2> else irb(main):022:2* "foo" irb(main):023:2> end irb(main):024:1> end irb(main):028:0> def task(tasktype) irb(main):029:1> if block_given? irb(main):030:2> yield(tasktype) irb(main):031:2> else irb(main):032:2* p tasktype irb(main):033:2> end irb(main):034:1> end irb(main):035:0> task foo { |t| p t } main nil => nil irb(main):036:0> task foo do |t| p t end "foo" => nil So, depending on who gets the block, different things happen. This can be prevented with parentheses: irb(main):037:0> task(foo) {|t| p t } "foo" => nil irb(main):039:0> task(foo do |t| p t end) main nil => nil But the second one looks ugly, and the first one has parenthesis, which I suppose reduces its poetic beauty. Personally, I would prefer that there be only one block type, with a set precedence, and that you be forced to use parentheses when that precedence isn't what you want. I think the lack of beauty is more than made up for by the lack of confusion. >> This leads to people having their own conventions, like using {} >> only when it's a one-line block, and do ... end when it's a >> multiline block; or using {} when it returns a value, but do ... >> end when it doesn't. > > That's a convention only cared about when the binding difference > isn't needed. Right, but I would guess that 90% or more of the time, the binding difference isn't an issue, so it's up to other concerns, like aesthetics. >> Whatever the resolution though, I would prefer to see a situation >> where only one of blocks and hashes used {}, despite the >> backwards-compatibility issues. > > On that, I'd agree. I wasn't sold, originally on the idea of [:] as > a null hash, but I think I prefer it overall. Yeah. I do too. I also thought about the possibility of something like the %q{} things we have now, like maybe %h[] or %h{}. They're a bit ugly, but save a little typing. Overall I like [:] better. I could even live with [=>] though that doesn't save you many keystrokes over Hash.new, and since most of those keystrokes are weird symbol chars that are not easy to type, I'd bet you can type Hash.new quicker. In the end though, it's up to Matz. I bet he'll do the right thing. He's proven so far to be great at designing a programmer-centric language. I just hope that he uses the opportunity of a major version bump to break backwards-compatibility and clean up a few dusty corners. Ben