[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Writing Good #each Methods?

James Herdman

3/14/2006 5:50:00 AM

I'm working my way through The Ruby Course slides at the moment and am
on the section about dynamicity. Specifically I'm on slide 59 right
now, the slide about a ListItem -- essentially a link list.

So, this got me thinking: what makes a good #each method? I'd love to
hear any pearls of wisdom if any of you have the time.

Thank you,

James H.

12 Answers

Farrel Lifson

3/14/2006 7:16:00 AM

0

> So, this got me thinking: what makes a good #each method? I'd love to
> hear any pearls of wisdom if any of you have the time.

I think an each method should have the following properties
* All elements must be yielded
* Each element must be yielded exactly once
* If the container has some order associated with it (ie Array or
SortedSet) the elements should be yielded in order
* If there is more than ordering (such as a post, pre or in order
walk round a binary tree) then the elements should be yielded
according to the ordering that is as closest to 'natural' ordering
(inorder in the case of a binary tree). each methods for the other
orderings (each_preorder, each_postorder) must also be provided.

That's my opinion, I'm sure other people might disagree with me here.

Farrel


Paul Battley

3/14/2006 9:06:00 AM

0

I'd also add
* If appropriate, inspect the arity of the block and provide the
requested number of parameters.

Hash#each's behaviour is a good example:
hash = {:a=>1, :b=>2}
hash.each { |x| p x }
# [:b, 2]
# [:a, 1]
hash.each { |k,v| puts "#{k.inspect} => #{v.inspect}" }
# :b => 2
# :a => 1

Paul.


Robert Klemme

3/14/2006 9:43:00 AM

0

Paul Battley wrote:
> I'd also add
> * If appropriate, inspect the arity of the block and provide the
> requested number of parameters.

And another one

* return self

robert

George Ogata

3/14/2006 10:07:00 AM

0

"Paul Battley" <pbattley@gmail.com> writes:

> I'd also add
> * If appropriate, inspect the arity of the block and provide the
> requested number of parameters.
>
> Hash#each's behaviour is a good example:
> hash = {:a=>1, :b=>2}
> hash.each { |x| p x }
> # [:b, 2]
> # [:a, 1]
> hash.each { |k,v| puts "#{k.inspect} => #{v.inspect}" }
> # :b => 2
> # :a => 1

You don't need to -- just yield the array.

irb(main):001:0> class C
irb(main):002:1> def each
irb(main):003:2> yield [1,2]
irb(main):004:2> yield [3,4]
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> C.new.each{|a| p a}
[1, 2]
[3, 4]
=> nil
irb(main):008:0> C.new.each{|a,b| p [a,b]}
[1, 2]
[3, 4]
=> nil

Paul Battley

3/14/2006 10:36:00 AM

0

> You don't need to -- just yield the array.

Oops. You are, of course, correct. If it is just an array, that
behaviour comes automatically.

Wouldn't it be nice if inject did the same, though? E.g.
hash.inject([]){ |acc, key, value| ... }

Paul.


George Ogata

3/14/2006 10:44:00 AM

0

"Paul Battley" <pbattley@gmail.com> writes:

> Wouldn't it be nice if inject did the same, though? E.g.
> hash.inject([]){ |acc, key, value| ... }

You can come close:

hash.inject([]){ |acc, (key, value)| ... }

Pit Capitain

3/14/2006 10:53:00 AM

0

Paul Battley schrieb:
> Wouldn't it be nice if inject did the same, though? E.g.
> hash.inject([]){ |acc, key, value| ... }

Paul, you have to use parentheses:

hash.inject([]){ |acc, (key, value)| ... }

Regards,
Pit


Paul Battley

3/14/2006 11:04:00 AM

0

> hash.inject([]){ |acc, (key, value)| ... }

Thanks! I hadn't thought to try that before. It's definitely going to
make my future use of inject more concise and readable.

Paul.


James Herdman

3/14/2006 4:00:00 PM

0

Concerning ordered elements, what is the best way to ascertain the
order wherein the structure is not an array? For instance, suppose you
had a link list. You *could* have a class variable that kept track of
the beginning, but this would mean difficulties when you had more than
one link list in play.

In trying to solve the order issue (naively), I wrote a method like:

def each(&block)
current = self.previous
until current.previous.nil?
current = current.previous
end

# ...
end

This obviously doesn't work because on each call of #each, the focus is
rewound to the intial element in the list.

Any advice on the matter?

James Herdman

3/14/2006 4:03:00 PM

0

I'm a little confused by this. As I understand it, "arity" is the
number of arguments to a term. Perhaps I'm just not seeing it in your
example, but where does arity fit into it? Doubly, why might one want
to know this?