Hi --

On Thu, 23 Nov 2006, Jason Mayer wrote:

> I thought I was going to get to contribute, but then I got stuck.  I
> installed the latest ruby, wrote a quick program that I thought would do it,
> and it didn't.  So I expanded on the program, trying to figure out what was
> going on, and now it's 20 lines long(mostly puts) and I *still* don't get
> something (Beware - the single most basic code ever follows - it was
> originally much nicer but then I got to trying to debug)

There are a few cobwebs you can clear :-)

> a = Array.new
> a = %w{test test2 test3}

You're using the identifier 'a' twice.  The first use is discarded.
You might as well do:

   a = 1000
   a = %w{ test test2 test3 }

The second assignment clobbers the first, with respect to the
variable.

> puts a
> aSize = a.size
> b = Array.new
> b = %w{test3 nil test2 test}

Do you really want the string "nil" there, as opposed to the object nil?

> bSize = b.size
> puts 'size of b:' + bSize.to_s
> puts b
> puts 'size of a:' + aSize.to_s
> if aSize = bSize

You mean:

   if aSize == bSize

> aSorted= a.sort!
> bSorted= b.sort!

This is OK if everything in both arrays is sortable, but they may not
be:

   [1,2,nil,3].sort  # => ArgumentError

You can't compare nil to an integer, nor a string to an integer, etc.,
so an array with mixed objects like that can't sort.

Here's another way to go about it.  I imagine someone will come along
with a slicker and/or more efficient implementation of the method, but
for what it's worth, here's mine:

require 'test/unit'

module EnumerableAddons

   def count(element)
     find_all {|e| e == element }.size
   end

   def equal_to(other)
     all? {|e| other.count(e) == count(e) }
   end
end

class ArrayComparisonTest < Test::Unit::TestCase

   def setup
     @a = [1,2,3,4,nil,"hi"].extend(EnumerableAddons)
     @b = [2,3,nil,4,"hi",1].extend(EnumerableAddons)
   end

   def test_same
     assert(@a.equal_to(@b))
   end

   def test_duplicate
     @a << 1
     assert(!@a.equal_to(@b))
   end

   def test_extra
     @a << 5
     assert(!@a.equal_to(@b))
   end

   def test_subset_of_same_size
     @a.pop
     @a << 1
     assert(!@a.equal_to(@b))
   end

end


There's an noteworthy lesson about testing here, by the way.  My first
implementation of equal_to was:

   def equal_to(other)
   end

Interestingly, some of my tests passed -- because the method returned
nil, and I was asserting (the truth of (not the method return value)).
It's a useful reminder of the possibility of things working by
coincidence sometimes.


David

-- 
                   David A. Black | dblack / wobblini.net
Author of "Ruby for Rails"   [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog)        [2] | Co-director, Ruby Central, Inc.   [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com    | [4] http://www.rubycentral.org