Project

General

Profile

Actions

Bug #11991

closed

`Symbol#match` returns the match position, unlike `String#match` and `Regexp#match`

Added by sawa (Tsuyoshi Sawada) over 8 years ago. Updated over 8 years ago.


Description

String#match and Regexp#match return a MatchData when match succeeds:

"".match(//) # => #<MatchData "">
//.match("") # => #<MatchData "">
//.match(:"") # => #<MatchData "">

But Symbol#match returns the match position (like String#=~):

:"".match(//) # => 0

Thus, Symbol#match behaves differently from String#match and Regexp#match. This is the documented behavior, but it may be a bug (together with the documentation).

On the other hand, if it is not a bug, what is the rationale?

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

Seems a bug, but "spec-style" test suit seems depending on the current behavior.

diff --git i/string.c w/string.c
index e4b323d..864f6c4 100644
--- i/string.c
+++ w/string.c
@@ -9253,7 +9253,6 @@ sym_casecmp(VALUE sym, VALUE other)
 /*
  * call-seq:
  *   sym =~ obj   -> fixnum or nil
- *   sym.match(obj)   -> fixnum or nil
  *
  * Returns <code>sym.to_s =~ obj</code>.
  */
@@ -9266,6 +9265,19 @@ sym_match(VALUE sym, VALUE other)
 
 /*
  * call-seq:
+ *   sym.match(obj)   -> MatchData or nil
+ *
+ * Returns <code>sym.to_s.match(obj)</code>.
+ */
+
+static VALUE
+sym_match_m(int argc, VALUE *argv, VALUE sym)
+{
+    return rb_str_match_m(argc, argv, rb_sym2str(sym));
+}
+
+/*
+ * call-seq:
  *   sym[idx]      -> char
  *   sym[b, n]     -> string
  *   sym.slice(idx)      -> char
@@ -9593,7 +9605,7 @@ Init_String(void)
     rb_define_method(rb_cSymbol, "length", sym_length, 0);
     rb_define_method(rb_cSymbol, "size", sym_length, 0);
     rb_define_method(rb_cSymbol, "empty?", sym_empty, 0);
-    rb_define_method(rb_cSymbol, "match", sym_match, 1);
+    rb_define_method(rb_cSymbol, "match", sym_match_m, -1);
 
     rb_define_method(rb_cSymbol, "upcase", sym_upcase, -1);
     rb_define_method(rb_cSymbol, "downcase", sym_downcase, -1);
diff --git i/test/ruby/test_symbol.rb w/test/ruby/test_symbol.rb
index 8960bec..f498fec 100644
--- i/test/ruby/test_symbol.rb
+++ w/test/ruby/test_symbol.rb
@@ -246,6 +246,30 @@
     assert_equal(:fOo, :FoO.swapcase)
   end
 
+  def test_MATCH # '=~'
+    assert_equal(10,  :"FeeFieFoo-Fum" =~ /Fum$/)
+    assert_equal(nil, "FeeFieFoo-Fum" =~ /FUM$/)
+
+    o = Object.new
+    def o.=~(x); x + "bar"; end
+    assert_equal("foobar", :"foo" =~ o)
+
+    assert_raise(TypeError) { :"foo" =~ "foo" }
+  end
+
+  def test_match_method
+    assert_equal("bar", :"foobarbaz".match(/bar/).to_s)
+
+    o = Regexp.new('foo')
+    def o.match(x, y, z); x + y + z; end
+    assert_equal("foobarbaz", :"foo".match(o, "bar", "baz"))
+    x = nil
+    :"foo".match(o, "bar", "baz") {|y| x = y }
+    assert_equal("foobarbaz", x)
+
+    assert_raise(ArgumentError) { :"foo".match }
+  end
+
   def test_symbol_poped
     assert_nothing_raised { eval('a = 1; :"#{ a }"; 1') }
   end

Updated by Eregon (Benoit Daloze) over 8 years ago

I would be happy to adapt the spec suite to the newer behavior if we decide so, of course.
However, I think such a change should be done not before the next minor (2.4) for potential incompatibility.

Updated by naruse (Yui NARUSE) over 8 years ago

  • Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.0.0: WONTFIX, 2.1: WONTFIX, 2.2: WONTFIX, 2.3: WONTFIX

Updated by naruse (Yui NARUSE) over 8 years ago

  • Status changed from Open to Assigned
  • Assignee set to nobu (Nobuyoshi Nakada)

Considered a bug but for compatibility this shouldn't be backported.

2.4 will introduce incompatibility.

Actions #5

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Status changed from Assigned to Closed

Applied in changeset r53866.


string.c: Symbol#match

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0