From: Michael Lucas-Smith Date: 2001-12-31T14:41:30+09:00 Subject: [ruby-talk:29809] Re: Proc.class vs yield David Alan Black wrote: > Hi -- > > On Mon, 31 Dec 2001, Michael Lucas-Smith wrote: > > >>> >>>So typically you'd see: >>> >>> def my_method(arg1, arg2, &block) >>> ... >>> end >>> >>>I'm not sure what you want to do in your example.... What are you >>>expecting &a and &b to be? >>> >>> >>Two proc's. It seems that I can't pass two procs to a method unless the >>calling method is horribly ugly. >> > > Passing Proc objects is inherently no uglier than passing any other > kind: > > pr1 = proc { |x| puts "My arg is #{x}" } > pr2 = proc { |x| puts "My arg * 2 is #{x * 2}" } > some_method(pr1,pr2) > > Neither of those procs, though, is the method call's block. You'd > have to specify that too, if you want to use one: > > some_method(pr1,pr2) { puts "This is the supplied block." } > > > David > > The reason I'm bringing this up is because having a criteria block of code and a failure block of code si very common in Smalltalk. For example: childrenOf: aPersonName in: people people detect: [:person | person name = aPersonName] ifFound: [:person | person children] ifNone: [OrderedCollection new] in normal ST-80, this might be written as: childrenOf: aPersonName in: people | namedPerson | (namedPerson := people detect: [:person | person name = aPersonName] ifNone: [nil]) isNil ifTrue: [OrderedCollection new] ifFalse: [namedPerson children] The standard ST-80 comes with lots of two-block methods to make things easy for you. I add a few three-block methods. As you can surely see, the first three-block example is easier to read than the two-block example. A one block example might be something along the lines of: def childrenOf (aPersonName, people) if (namedPerson := people.detect { |person| person.name = aPersonName }) then return namedPerson.children else return Array.new end end I'm not really too fussed on how easily one can be written or the other, but what I am interested in is readability. The first three-block example does exactly what it says. The second two-block example is harder to read because ST-80 normally exceptions when detect: fails, thus you have to call detect:ifNone:. The one-block Ruby example takes advantage of the true/false nil/not-nil tricks, but is still not as readable as the three-block example. What I'm really trying to point out is, it's a real shame that you are forced to add this 'proc' thing before your blocks of code. To do something similar to the three-block example in Ruby you'd have: def childrenOf (aPersonName, people) return people.detect proc { |person| person.name = aPersonName }, proc { |person| person.children}, proc { Array.new } end When really, I want to be able to write: def childrenOf (aPersonName, people) return people.detect { |person| person.name = aPersonName }, { |person| person.children }, { Array.new } end But there are two things stopping me. (1) The parser spits at having the first argument start on the second line (2) I need to explicitely say they're procs. Michael