Extrange String#=~ behaviour

Hi, I can't understand it:

  class String
    def =~ obj
      puts "Sorry, I don't compare"
    end
  end

a) OK

"string" =~ 1234

Sorry, I don't compare
nil

b) ¿?

"string" =~ /string/

0

c) OK

"string".send(:"=~", 1234)

Sorry, I don't compare
nil

d) OK

"string".send(:"=~", /string/)

Sorry, I don't compare
nil

Could I know why case "b" perform the normal regexp comparission instead of
invoking the re-defined String#=~ method??

Thanks.

···

--
Iñaki Baz Castillo

Sorry, the subject must be "Strange" :slight_smile:

···

--
Iñaki Baz Castillo

Iñaki Baz Castillo wrote:

Hi, I can't understand it:

  class String
    def =~ obj
      puts "Sorry, I don't compare"
    end
  end

b) ¿?
> "string" =~ /string/
0

Could I know why case "b" perform the normal regexp comparission instead
of
invoking the re-defined String#=~ method??

To me that suggests that String#=~ calls Regexp#=~. However, I am
having no luck proving that. I can't even override Regexp#=~:

class Regexp
  def =~(obj)
    puts "goodbye"
  end
end

puts /string/ =~ "string" #0

···

--
Posted via http://www.ruby-forum.com/\.

Iñaki Baz Castillo wrote:

Could I know why case "b" perform the normal regexp comparission instead
of
invoking the re-defined String#=~ method??

ParseTree gem may help you.

$ cat strange.rb
class String
  def =~ obj
    puts "Sorry, I don't compare"
  end
end

r1 = "string" =~ 1234
r2 = "string" =~ /string/
r3 = "string".send(:"=~", 1234)
r4 = "string".send(:"=~", /string/)

$ parse_tree_show strange.rb
s(:block,
s(:class,
  :String,
  nil,
  s(:scope,
   s(:defn,
    :=~,
    s(:scope,
     s(:block,
      s(:args, :obj),
      s(:fcall, :puts, s(:array, s(:str, "Sorry, I don't
compare")))))))),
s(:lasgn, :r1, s(:call, s(:str, "string"), :=~, s(:array, s(:lit,
1234)))),
s(:lasgn, :r2, s(:match3, s(:lit, /string/), s(:str, "string"))),
s(:lasgn,
  :r3,
  s(:call, s(:str, "string"), :send, s(:array, s(:lit, :=~), s(:lit,
1234)))),
s(:lasgn,
  :r4,
  s(:call,
   s(:str, "string"),
   :send,
   s(:array, s(:lit, :=~), s(:lit, /string/)))))
$

You can see that your case (b) is parsed differently as a :match3,
bypassing the normal method dispatch (:call)

···

--
Posted via http://www.ruby-forum.com/\.

Iñaki Baz Castillo wrote:

Hi, I can't understand it:

class String
def =~ obj
puts "Sorry, I don't compare"
end
end

b) ¿?
> "string" =~ /string/
0

Turns out using Regexp.new behaves as expected:

07> "string" =~ Regexp.new('string')
Sorry, I don't compare
--> nil

class Regexp
def =~(obj)
puts "goodbye"
end
end

puts /string/ =~ "string" #0

In this case too:

08> Regexp.new('string') =~ "string"
goodbye
--> nil

Ruby 1.9 rdoc for Regexp#=~ hints at special treatment for regexp literals [1]:
"This assignment is implemented in the Ruby parser. So a regexp
literal is required for the assignment. The assignment is not occur if
the regexp is not a literal."
But that is in the context of assigning to ?<var> type named captures
within a regexp on the LHS, so i don't know if it's relevant.

Hope someone who knows the implementation can shed more light.

Cheers,
lasitha.

[1] class Regexp - RDoc Documentation

···

On Wed, Feb 25, 2009 at 8:05 AM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

Interesting, thanks a lot.

···

2009/2/25 Brian Candler <b.candler@pobox.com>:

You can see that your case (b) is parsed differently as a :match3,
bypassing the normal method dispatch (:call)

--
Iñaki Baz Castillo
<ibc@aliax.net>