[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Re: iterate chars in a string

Ross Bamford

3/21/2006 10:09:00 AM

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?

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk



2 Answers

Clint

3/21/2006 11:11:00 AM

0

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

Dave Burt

3/21/2006 12:23:00 PM

0

Mike Austin wrote:
> 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

I believe Ruby 1.9 (experimental) has this feature.

Cheers,
Dave