From: Mike Austin Date: 2006-03-21T20:13:50+09:00 Subject: Re: iterate chars in a string Ross Bamford wrote: > On Tue, 2006-03-21 at 18:47 +0900, Robert Dober wrote: >> Sorry Robert but I do not think I made myself too clear >> >> we now about each_byte and I already combined your #chr and String#each_byte >> >> so we had already established >> >> "Ty Mr. Klemme".each_byte { |b| puts b.chr } >> >> which is pretty elegant, don't you agree? >> So Enumerators are not needed. >> > > Duck typing? > > require 'enumerator' > > def just_iterate(obj) > obj.each { |e| p e } > end > > just_iterate("abc") > # (prints) "abc" > > just_iterate("abc".enum_for(:each_byte)) > # (prints) 97 > # 98 > # 99 > >> Now after that we switched discussing the behaviour of String#each and I >> *really* feal that String#each should us give that kind of behaviour. >> As I see that a lot of people think that the current behaviour of >> String#each is a good one, and changing it would not be an option anyway I >> thaught that the only solution would be to enhance the behaviour of >> String#each. >> The idea for that behaviour comes from Ruby itself (look at IO#gets) >> >> then >> >> "Ty Mr. Klemme".each_byte { |b| puts b.chr } >> >> would be the same as >> >> "Ty Mr. Klemme".each( 1 ) { |b| puts b } >> >> There is always more than one way to do it ;) > > Umm, there's *already* more than one way to do it :) But Enumerator > really is a very useful class: > > "abc\ndef\nghi\njkl".each { |e| p e } > # "abc\n" > # "def\n" > # "ghi\n" > # "jkl" > > "abc\ndef\nghi\njkl\n".enum_for(:each_byte).each { |e| p e.chr } > # "a" > # "b" > # "c" > # "\n" > # "d" > # "e" > # etc. > > "abc\ndef\nghi\njkl\n".enum_slice(2).each { |e| p e } > # ["abc\n", "def\n"] > # ["ghi\n", "jkl\n"] > > "abc\ndef\nghi\njkl\n".enum_for(:each_byte).enum_slice(2).each { |e| p e } > # [97, 98] > # [99, 10] > # [100, 101] > > And crucially: > > "abc\ndef\nghi\njkl\n".enum_for(:each_byte).enum_slice(2).map do |(a,b)| > (a + b).chr > end > # => ["\303", "m", "\311", "p", "\317", "s", "\325", "v"] > > How would map and other Enumerable methods work if 'each' needed > arguments? Maybe a little off the topic, but I still think it would be pretty nifty if calling enumerators without a block returned it's own enum_for(): "abcdefg".each_byte.each_slice(2).map do |a, b| (a + b).chr end To me it feels like partial application. It can't do anything without a block, so it simply passes its enumerator. No more messy 'enum_for()'s littered everywhere. Here's another example: "abcdefg".each_byte.with_index.map do |a, i| a + i end Just my 2c, and thinking out loud Mike