views:

103

answers:

4

So how can I still be able to write beautiful code such as:

'im a string meing!'.pop

Note: str.chop isn't suffecient answer

+1  A: 

That's not beautiful :)

Also #pop is not part of Enumerable, it's part of Array.

The reason why String is not enumerable is because there are no 'natural' units to enumerate, should it be on a character basis or a line basis? Because of this String does not have an #each

String instead provides the #each_char and #each_byte and #each_line methods for iteration in the way that you choose.

banister
I know, I'm learning. But it's a lot better than str[str.lenght]
Zombies
Use str[-1] to get the last character.
banister
I know but I'm kind of anal retentive about this atm. Well actually that isn't too bad.
Zombies
A: 

Since you don't like str[str.length], how about

'im a string meing!'[-1]  # returns last character as a character value

or

'im a string meing!'[-1,1]  # returns last character as a string

or, if you need it modified in place as well, while keeping it an easy one-liner:

class String
  def pop
    last = self[-1,1]
    self.chop!
    last
  end
end
Matt
pop removes the element as well. Not sure if that's one of his requirements.
Beanish
True, it does remove the last element and that does make things more complex. These are still good alternatives to learn from for me though.
Zombies
updated to remove the last character as well (in the String::pop definition)
Matt
+4  A: 

It is not what an enumerable string atually enumerates. Is a string a sequence of ...

  • lines,
  • characters,
  • codepoints or
  • bytes?

The answer is: all of those, any of those, either of those or neither of those, depending on the context. Therefore, you have to tell Ruby which of those you actually want.

There are several methods in the String class which return enumerators for any of the above. If you want the pre-1.9 behavior, your code sample would be

'im a string meing!'.bytes.to_a.pop

This looks kind of ugly, but there is a reason for it: a string is a sequence. You are treating it as a stack. A stack is not a sequence, in fact it pretty much is the opposite of a sequence.

Jörg W Mittag
Nice answer, but the string still has all of its original characters in memory.
Zombies
well, you could always `def String.pop; self.bytes.to_a.pop; end` I suppose.
Shadowfirebird
+1  A: 
#!/usr/bin/ruby1.8

s = "I'm a string meing!"
s, last_char = s.rpartition(/./)
p [s, last_char]    # => ["I'm a string meing", "!"]

String.rpartition is new for 1.9 but it's been back-ported to 1.8.7. It searches a string for a regular expression, starting at the end and working backwards. It returns the part of the string before the match, the match, and the part of the string after the match (which we discard here).

Wayne Conrad