ruby picture

RCR 283: add String#first and String#last

Submitted by neoneye (Sun Oct 24 11:10:49 UTC 2004)

Abstract

When looking at the Array class I see that it has #first and #last methods, just for this purpose, to extract the sub-array either from the beginning or the ending. Why not also use #first and #last on String ?

Problem

I often use a range to extract the beginning/ending letters.. like this   "string"[-4, 4] #-> "ring" It feels somewhat redundant that I have to type the length 2 times. A very simple operation that easily can confuse people if they are browsing through others code.. this is a place where one easily can introduce off-by-one errors.

There are many ways to extract the ending substring, which IMHO is less clean, such as "string"[/.{4}\z/] and "string"[2..-1] .

Proposal

"ruby".first(2)  #=> "ru"
"ruby".last(3)  #=> "uby"

Analysis

Some encodings has variable length chars, where a char may span between 1 and 5 bytes. This raises the question: how should the argument to #first be interpreted? should it interpret as bytes or chars?

Should there be aliases #left and #right ?

Implementation

class String
  def first(length=nil)
    length ||= 1
    unless length.respond_to?(:to_int)
      raise TypeError, "cannot convert #{length.class} to Integer"
    end
    n = length.to_int
    unless n.kind_of?(Integer)
      raise TypeError, "#{length.class}#to_int should return Integer"
    end
    raise ArgumentError, "negative string size" if n < 0
    n = [n, self.size].min
    self[0, n]
  end
  def last(length=nil)
    length ||= 1
    unless length.respond_to?(:to_int)
      raise TypeError, "cannot convert #{length.class} to Integer"
    end
    n = length.to_int
    unless n.kind_of?(Integer)
      raise TypeError, "#{length.class}#to_int should return Integer"
    end
    raise ArgumentError, "negative string size" if n < 0
    n = [n, self.size].min
    self[-n, n]
  end
end
ruby picture
Comments Current voting
These are fine, although maybe a bit over done. Unfortunately I think Ruby lends itself to needing methods like this since there is some oddness to how #slice works. I'd vote "in favor" for improved/lighter versions. --T.


a useful addition --gmosx


I'm voting "Neutral" (why would anyone do that?). I like

          
   "string"[:n] (from the beginning to index "n")
and
          

          
   "string"[n:] (from index "n" to the end)
- but that's Pyth..Errr Icon syntax and it would be incompatible with Ruby's :symbols.
          

"string".first(n) and "string".last(n) don't get any closer to a compact form, but I share your feelings about "string"[-4, 4] requiring the length twice. I've always felt there's something "not quite there" about Ruby's slice method. --daz


Strongly opposed 0
Opposed 1
Neutral 1
In favor 5
Strongly advocate 1
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .