From: Robert Klemme Date: 2004-08-10T18:51:15+09:00 Subject: Re: FirstEachLast, an extension to the Enumerable module. "Alexander Kellett" schrieb im Newsbeitrag news:20040810090629.GA13191@loki... > On Tue, Aug 10, 2004 at 03:46:17PM +0900, Robert Klemme wrote: > > Hm, sounds to me like it was not general enough to include it in > > Enumerable. Before I see that method I'd prefer to have size and empty? > > in Enumerable. Just my 0.02 EUR... > > personally the idea of having a method taking 4 procs > in the stdlib is just a bit strange. Agreed. > i'd prefer to see > a generic set of methods that are somehow mixedin to > the values that a Enumerable yields, therefore allowing > things like val.last? or first? or even a generic > val.enum_index to replace the each_with_index rubbish. > i've no idea how to solve this neatly unfortunately as > extend'ing the objects that are yield'ed of course will > have sideeffects... though most of the side effects that > will cause problems shouldn't happen at all, e.g people > calling is_a? a lot will have problems... I strongly disagree. All sorts of problems arise from this approach: - permanent modification of elements' types - method name collisions - member state collisions - thread problems (1 instance used during two parallel iterations) The index clearly belongs to the *iteration* and not the elements. Possible solutions: - yield not the instance but an iteration state that has the current item as member - use delegator (this avoids permanent changes but has still method collision problems) > i do this > and yet i don't have an exception to such an extension... > but this: > > blah.each { > |element| > pos = blah.index element > puts blah[pos-1] > puts element > } > > is soooooo uggllyyy... not to mention inefficient... > i'd just loooveeee to see a element.previous_in_enum... First of all you don't cope with the first element properly. Then, there are simple and efficient solutions available. To name some: # for Arrays blah.each_with_index { |element, pos| puts blah[pos-1] if pos != 0 puts element } NOTHING = Object.new last = NOTHING blah.each { |element| puts last if NOTHING != last puts element last = element } NOTHING = Object.new blah.inject(NOTHING) { |last, element| puts last if NOTHING != last puts element element } NOTHING = Object.new blah.inject(NOTHING) { |last, element| process last if NOTHING != last element } process last if NOTHING != last etc. depending on what you want to do. Regards robert