Feature #7883

Add Regex#to_proc

Added by Robert Klemme over 2 years ago. Updated 5 months ago.

[ruby-core:52514]
Status:Open
Priority:Normal
Assignee:Yukihiro Matsumoto

Description

Just a small addition to the standard library:

class Regexp
  def to_proc; lambda {|s| self =~ s} end
end

With that one can use a Regexp everywhere a Proc is used as filtering criteria saving a bit of typing. While we have Enumerable#grep already there may be other cases where you want to do something like

irb(main):008:0> %w{foo bar baz}.select &/\Ab/
=> ["bar", "baz"]
irb(main):009:0> %w{foo bar baz}.reject &/\Ab/
=> ["foo"]
irb(main):010:0> %w{foo bar baz}.find &/\Ab/
=> "bar"

Note: line 9 and 10 are not possible with Enumerable#grep AFAIK.

I see low risk of breaking something.

History

#1 Updated by Nobuyoshi Nakada over 2 years ago

You can use /\Ab/.method(:=~).

#2 Updated by Charlie Somerville over 2 years ago

You can use /\Ab/.method(:=~).

This is more typing than just using '{ |x| x =~ /\Ab/ }'.

I like this idea, it's something I have to do quite often.

I've also wanted a 'grep_v' method before, but reject with Regexp#to_proc would suit perfectly.

#3 Updated by Alex Young over 2 years ago

On 19/02/2013 07:58, rklemme (Robert Klemme) wrote:

Issue #7883 has been reported by rklemme (Robert Klemme).

Lovely. Definite +1 from me (for whatever that's worth).

Alex

#4 Updated by Robert Klemme over 2 years ago

nobu (Nobuyoshi Nakada) wrote:

You can use /\Ab/.method(:=~).

Yes, but that's not the point. In that case I'd prefer the real block as Charlie suggested.

#5 Updated by Ilya Vorontsov over 2 years ago

Cool idea. +1

#6 Updated by Magnus Holm over 2 years ago

class Regexp
  def to_proc; lambda {|s| self =~ s} end
end

A more general case:

class Object
  def to_proc
    lambda { |other| self === other }
  end
end

(Not that I think this is going to be accepted…)

#7 Updated by Lee Jarvis over 2 years ago

I like this, and I especially like the modified version from judofyr. You could also do ["abc", 3, "foo", etc].find(&Integer) which is neat, but maybe that's a push in the wrong direction, I'm not sure.

#8 Updated by Gosha Arinich over 2 years ago

Nice one, +1 on it as well.

#9 Updated by jy j over 2 years ago

judofyr (Magnus Holm) wrote:

class Regexp
  def to_proc; lambda {|s| self =~ s} end
end

A more general case:

class Object
  def to_proc
    lambda { |other| self === other }
  end
end

(Not that I think this is going to be accepted…)

cool!

#10 Updated by Koichi Sasada over 2 years ago

  • Target version changed from 1.9.3 to next minor
  • Assignee set to Yukihiro Matsumoto

#11 Updated by Robert Klemme 5 months ago

Was any of the two suggested forms ever realized?

#12 Updated by Nobuyoshi Nakada 5 months ago

  • Description updated (diff)

Nothing, and line 10 is possible with grep

%w{foo bar baz}.grep(/\Ab/) {|s|break s}

Anyway, a patch.

diff --git i/re.c w/re.c
index 1a0f0b1..d345f17 100644
--- i/re.c
+++ w/re.c
@@ -801,6 +801,19 @@ rb_reg_named_captures(VALUE re)
     return hash;
 }

+static VALUE
+rb_reg_to_proc(VALUE re)
+{
+    const ID id = 1;
+    VALUE proc = rb_attr_get(re, id);
+    if (NIL_P(proc)) {
+   proc = rb_obj_method(re, ID2SYM(rb_intern("=~")));
+   proc = rb_funcall(proc, rb_intern("to_proc"), 0, 0);
+   rb_ivar_set(re, id, proc);
+    }
+    return proc;
+}
+
 static int
 onig_new_with_source(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
      OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
@@ -3660,6 +3673,7 @@ Init_Regexp(void)
     rb_define_method(rb_cRegexp, "fixed_encoding?", rb_reg_fixed_encoding_p, 0);
     rb_define_method(rb_cRegexp, "names", rb_reg_names, 0);
     rb_define_method(rb_cRegexp, "named_captures", rb_reg_named_captures, 0);
+    rb_define_method(rb_cRegexp, "to_proc", rb_reg_to_proc, 0);

     /* see Regexp.options and Regexp.new */
     rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));

#13 Updated by Robert Klemme 5 months ago

Nobuyoshi Nakada wrote:

Nothing, and line 10 is possible with grep

%w{foo bar baz}.grep(/\Ab/) {|s|break s}

Yes, but a bit lengthy.

Anyway, a patch.

Cool! Thanks a lot!

#14 Updated by Tsuyoshi Sawada 5 months ago

If the proposed patch to issue #9602 gets accepted, then that will covert this issue in a more general way.

Also available in: Atom PDF