Feature #3388

regexp support for start_with? and end_with?

Added by Thomas Sawyer almost 4 years ago. Updated over 1 year ago.

[ruby-core:30585]
Status:Feedback
Priority:Normal
Assignee:Yui NARUSE
Category:core
Target version:next minor

Description

=begin
ruby-1.9.2-head > "aBcdeFghIj".start_with?(/abc/i)
=> false

In my implementation of start_with? it is easy enough to utilize #index, which works fine:

def start_with?(pattern)
index(pattern) == 0
end

But #end_with? is more difficult, and I had to use regular expressions.

 def end_with?(suffix)
   suffix = Regexp.escape(suffix) if String===suffix
   /#{suffix}$/.match(self) ? true : false
 end

However, we might get rid of the '? true : false' and return the MatchData, since that could be useful information.
=end

0001-string.c-rb_str_start_with-rb_str_end_with-allow-Reg.patch Magnifier (4.08 KB) Benoit Daloze, 08/26/2012 11:20 PM


Related issues

Duplicated by ruby-trunk - Bug #5536: String#start_with? and end_with? ignore arguments convert... Closed 11/01/2011

History

#1 Updated by Yui NARUSE almost 4 years ago

  • Status changed from Open to Rejected

=begin

=end

#2 Updated by Nobuyoshi Nakada almost 4 years ago

=begin
Not a bug.
=end

#3 Updated by Yui NARUSE almost 4 years ago

=begin
def endwith?(suffix)
if suffix.kind
of(String)
index(suffix) + suffix.length == self.length
else
m = suffix.match(self)
m ? m.post_match.empty? : false
end
end
=end

#4 Updated by Marc-Andre Lafortune almost 4 years ago

  • Category set to core

=begin
I'm moving this to the feature's tracker, since I feel it would make a valid addition.

PS: Yui, that code won't work:

 "Hello world. Bye".end_with? /e/ # => false

=end

#5 Updated by Marc-Andre Lafortune almost 4 years ago

  • Category set to core
  • Status changed from Rejected to Open
  • Target version set to 2.0.0

=begin

=end

#6 Updated by Nobuyoshi Nakada almost 4 years ago

=begin
def start_with?(pattern)
!!rindex(pattern, 0)
end

def end_with(pattern)
rindex(pattern) and (!$& || $~.end(0) == length) or false
end

=end

#7 Updated by Nobuyoshi Nakada almost 4 years ago

=begin
Missed.

def end_with?
i = rindex(pattern) and ($& ? $~.end(0) : i + pattern.length) == length or false
end

or

def end_with?(pattern)
if String === pattern
!!index(pattern, -pattern.length)
else
rindex(pattern) and $~.end(0) == length or false
end
end

=end

#8 Updated by Hiroshi Nakamura about 2 years ago

  • Description updated (diff)

rindex(pattern) would fail to detect proper endofstring index. It must be /{suffix}\Z/.

#9 Updated by Akira Tanaka about 2 years ago

I think we can cache regexp structure according to regexp source, options, encoding.

If regexp structure is cached, /\A#{pattern}/ and /#{pattern}\z/ is not slow for
second and successive dynamic regexp creation.

If it is not slow, we can use them to implement String#{startwith?,endwith?} for regexp.

#10 Updated by Yusuke Endoh about 2 years ago

  • Status changed from Open to Feedback

A patch is welcome.

Yusuke Endoh mame@tsg.ne.jp

#11 Updated by Benoit Daloze about 2 years ago

A patch is welcome.

I'm willing to give this a shot, but I think #5536 should be merged first.

#12 Updated by Benoit Daloze over 1 year ago

Here is an attempt adding \A or \z to the Regexp's source and creating a new Regexp with it.
An alternative would be to call #to_s on the Regexp and add the anchor, but it seems cleaner to preserve options as global options.

What do you think?

akr: How would you cache the regexp structure?

#13 Updated by Koichi Sasada over 1 year ago

  • Assignee set to Yui NARUSE

#14 Updated by Benoit Daloze over 1 year ago

I had a try implementing a global persistent cache for Regexps.

Is a global persistent cache OK? It seems bad for dynamically created regexps.
Maybe some kind of weak reference map?

akr: What kind of cache did you think to?

#15 Updated by Charles Nutter over 1 year ago

JRuby currently does have a global cache for regexps. If you're interested, one of us can show you how it works.

#16 Updated by Benoit Daloze over 1 year ago

headius (Charles Nutter) wrote:

JRuby currently does have a global cache for regexps. If you're interested, one of us can show you how it works.

Interesting. I see it's implemented using a SoftReference map.
I'm not aware of something similar in MRI.

If I read right, the only Regexp cache in MRI is a single last-used cache used in some String methods (match,scan,split,...).

It would be nice if we could differentiate static and dynamic regexps, but in any case I guess I could do a last-used cache as in re.c.

#17 Updated by Yusuke Endoh over 1 year ago

  • Target version changed from 2.0.0 to next minor

Also available in: Atom PDF