Set and Object equivilence

Discussion in 'Ruby' started by andrew.oxenburgh@gmail.com, Dec 11, 2007.

  1. Guest

    Hi,

    I've just started with Ruby from Java, and am having trouble getting a
    set to recognise equivalence between objects. Basically it is adding
    multiple equal objects to the set.

    I have created a class and overridden all of the operators <=> , ==,
    <, >, eqls?, equals?, hash to indicate that it should use an internal
    variable to compare.

    Please find enclosed a unit test, the object, and the output from the
    test. Cool language BTW. Really enjoying it up until this moment. I'm
    probably missing some subtlety of the language.

    Any help greatly appreciated.
    -------- source starts --------

    require "test/unit"
    require "set"

    class JunkTest < Test::Unit::TestCase
    def test_arraysMuckingAroundWith
    a = Thingy.new(1)
    b = Thingy.new(2)
    c = Thingy.new(1)
    d=Set.new
    d << a
    d << b
    d << c
    puts "output set, with duplicates - the first 2 object should
    be equivilent" + d.sort.to_s
    end
    end

    class Thingy

    attr_accessor :value

    def <=> (thing)
    self.value <=> thing.value
    end

    def == (thing)
    self.value == thing.value
    end

    def > (thing)
    self.value > thing.value
    end

    def < (thing)
    self.value < thing.value
    end

    def eqls? (thing)
    self.value.eqls?(thing.value)
    end

    def equals? (thing)
    self.value.equals?(thing.value)
    end

    def initialize(val)
    @value = val
    end

    def hash
    puts "hash " + @value.hash.to_s
    @value.hash
    end

    def to_s
    value.to_s + ", "
    end
    end
    -------- source ends --------

    -------- output starts --------

    C:\dev\ruby\bin\ruby.exe -e
    "STDOUT.sync=true;STDERR.sync=true;load($0=ARGV.shift)" C:/projects/
    SearchJars/test/JunkTest.rb --name test_arraysMuckingAroundWith
    Loaded suite C:/projects/SearchJars/test/JunkTest
    Started
    hash 3
    hash 5
    hash 3
    output set, with duplicates - 1, 1, 2,
    ..
    Finished in 0.0 seconds.

    1 tests, 0 assertions, 0 failures, 0 errors

    Process finished with exit code 0

    -------- output ends --------

    Regards



    Andrew Oxenburgh
     
    , Dec 11, 2007
    #1
    1. Advertising

  2. Gary Wright Guest

    On Dec 11, 2007, at 10:07 AM, wrote:
    >
    > def eqls? (thing)
    > self.value.eqls?(thing.value)
    > end


    You've got the name wrong, it should be eql?(thing).


    >
    > def equals? (thing)
    > self.value.equals?(thing.value)
    > end
    >


    You probably mean equal?(thing), but you should never redefine
    equal?(x) anyway as it always assumed to be an object identity
    test.

    Gary Wright
     
    Gary Wright, Dec 11, 2007
    #2
    1. Advertising

  3. 2007/12/11, <>:
    > Hi,
    >
    > I've just started with Ruby from Java, and am having trouble getting a
    > set to recognise equivalence between objects. Basically it is adding
    > multiple equal objects to the set.
    >
    > I have created a class and overridden all of the operators <=> , ==,
    > <, >, eqls?, equals?, hash to indicate that it should use an internal
    > variable to compare.
    >
    > Please find enclosed a unit test, the object, and the output from the
    > test. Cool language BTW. Really enjoying it up until this moment. I'm
    > probably missing some subtlety of the language.
    >
    > Any help greatly appreciated.
    > -------- source starts --------
    >
    > require "test/unit"
    > require "set"
    >
    > class JunkTest < Test::Unit::TestCase
    > def test_arraysMuckingAroundWith
    > a = Thingy.new(1)
    > b = Thingy.new(2)
    > c = Thingy.new(1)
    > d=Set.new
    > d << a
    > d << b
    > d << c
    > puts "output set, with duplicates - the first 2 object should
    > be equivilent" + d.sort.to_s
    > end
    > end
    >
    > class Thingy
    >
    > attr_accessor :value
    >
    > def <=> (thing)
    > self.value <=> thing.value
    > end
    >
    > def == (thing)
    > self.value == thing.value
    > end
    >
    > def > (thing)
    > self.value > thing.value
    > end
    >
    > def < (thing)
    > self.value < thing.value
    > end
    >
    > def eqls? (thing)


    Spelling error: this method needs to read "eql?". This is likely the
    cause for your issue.

    > self.value.eqls?(thing.value)
    > end
    >
    > def equals? (thing)
    > self.value.equals?(thing.value)
    > end
    >
    > def initialize(val)
    > @value = val
    > end
    >
    > def hash
    > puts "hash " + @value.hash.to_s
    > @value.hash
    > end
    >
    > def to_s
    > value.to_s + ", "
    > end
    > end
    > -------- source ends --------
    >
    > -------- output starts --------
    >
    > C:\dev\ruby\bin\ruby.exe -e
    > "STDOUT.sync=true;STDERR.sync=true;load($0=ARGV.shift)" C:/projects/
    > SearchJars/test/JunkTest.rb --name test_arraysMuckingAroundWith
    > Loaded suite C:/projects/SearchJars/test/JunkTest
    > Started
    > hash 3
    > hash 5
    > hash 3
    > output set, with duplicates - 1, 1, 2,
    > .
    > Finished in 0.0 seconds.
    >
    > 1 tests, 0 assertions, 0 failures, 0 errors
    >
    > Process finished with exit code 0
    >
    > -------- output ends --------


    It seems the output does not stem from the code you present because
    the print statement looks different.

    Few remarks: you can make your life easier by including Comparable and
    only implementing <=>; then <, <=, > and >= will be automatically be
    derived.

    You can make your life even simpler by just doing

    Thing = Struct.new :value

    Cheers

    robert

    --
    use.inject do |as, often| as.you_can - without end
     
    Robert Klemme, Dec 11, 2007
    #3
  4. Eric I. Guest

    Hi Andrew,

    First, change your .eqls? method to .eql? and that will fix your code.

    Also, you should look into the Comparable mix-in module. Basically,
    if you define the spaceship operator (<=>) and include Comparable in
    your class, it will define it will define all the relational operators
    (==, <, <=, >, >=) and between? for you. Plus, != is internally
    implemented as the boolean negation of ==, so you get that also.

    For Set member equality, two methods are used -- eql? and hash.

    Eric

    ====

    On-site, hands-on Ruby training is available from http://LearnRuby.com
    !
     
    Eric I., Dec 11, 2007
    #4
  5. Guest

    Thanks. Bit embarrassed with a simple spelling error. I looked at it
    for ages, and tried all sorts of permutations and combinations of set
    c'strs and adding methods!

    I'll check out the Comparable mixin as well.

    Regards


    On Dec 11, 3:30 pm, "Eric I." <> wrote:
    > Hi Andrew,
    >
    > First, change your .eqls? method to .eql? and that will fix your code.
    >
    > Also, you should look into the Comparable mix-in module. Basically,
    > if you define the spaceship operator (<=>) and include Comparable in
    > your class, it will define it will define all the relational operators
    > (==, <, <=, >, >=) and between? for you. Plus, != is internally
    > implemented as the boolean negation of ==, so you get that also.
    >
    > For Set member equality, two methods are used -- eql? and hash.
    >
    > Eric
    >
    > ====
    >
    > On-site, hands-on Ruby training is available fromhttp://LearnRuby.com
    > !
     
    , Dec 11, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Parthiv Joshi
    Replies:
    2
    Views:
    718
    Kalyan
    Jul 2, 2004
  2. Suresh Kojhani
    Replies:
    1
    Views:
    2,428
    Anushi
    Jul 29, 2004
  3. Replies:
    1
    Views:
    391
    Ken Cox [Microsoft MVP]
    Nov 5, 2004
  4. Fendi Baba
    Replies:
    0
    Views:
    312
    Fendi Baba
    May 13, 2007
  5. Replies:
    1
    Views:
    3,785
    Muhammad Naveed Yaseen
    Mar 3, 2008
Loading...

Share This Page