Skip to content

Add Node#hash and Node#eql? for correct Hash key behavior#25

Open
takahashim wants to merge 1 commit into
serpapi:masterfrom
takahashim:add-hash-eql
Open

Add Node#hash and Node#eql? for correct Hash key behavior#25
takahashim wants to merge 1 commit into
serpapi:masterfrom
takahashim:add-hash-eql

Conversation

@takahashim

Copy link
Copy Markdown

This PR adds Nokolexbor::Node#hash and Node#eql? for use as Hash keys and Set members.

Ruby requires that a == b implies a.eql?(b) and a.hash == b.hash.
Nokolexbor's Node#== already does C-pointer comparison, but hash and eql? fall back to per-Ruby-object identity.
As a result, two wrappers of the same C node behave inconsistently:

n1 = doc.at_css("div")
n2 = doc.at_css("div")

n1 == n2          # => true
n1.eql?(n2)       # => false
n1.hash == n2.hash # => false

{ n1 => "x" }[n2] # => nil  (lookup miss)

After this PR, eql? matches ==, and hash is derived from the C node pointer, so Hash and Set work as expected.

Example

require "nokolexbor"

doc = Nokolexbor::HTML("<div id='x'><p>hi</p></div>")

n1 = doc.at_css("#x")
n2 = doc.at_css("#x")

cache = { n1 => "value" }
cache[n2]                  # => "value"

[n1, n2, doc.at_css("p")].uniq.size # => 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant