Forum: Ruby Extrange String#=~ behaviour

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-02-24 20:54
(Received via mailing list)
Hi, I can't understand it:

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


a) OK
irb> "string" =~ 1234
Sorry, I don't compare
nil

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

c) OK
irb> "string".send(:"=~", 1234)
Sorry, I don't compare
nil

d) OK
irb> "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.
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-02-24 20:54
(Received via mailing list)
Sorry, the subject must be "Strange" :)
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-02-25 03:35
Iñaki Baz Castillo wrote:
> Hi, I can't understand it:
>
>   class String
>     def =~ obj
>       puts "Sorry, I don't compare"
>     end
>   end
>
> b) ¿?
> irb> "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
E16e84e861c1815ce11ba7bd851c857d?d=identicon&s=25 lasitha (Guest)
on 2009-02-25 08:11
(Received via mailing list)
On Wed, Feb 25, 2009 at 8:05 AM, 7stud -- <bbxx789_05ss@yahoo.com>
wrote:
>> irb> "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] http://ruby-doc.org/core-1.9/classes/Regexp.html#M001214
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-25 16:39
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)
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-02-25 18:31
(Received via mailing list)
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)

Interesting, thanks a lot.
This topic is locked and can not be replied to.