OK... :) question about hash and array literals

Hi,

Personally, I'd like it to remember the order you added things in, use
that ordering when iterating through the hash, and _optionally_ use it
for compares.

Hmm, I thought hash order would be ignored always for compares.
Optional use of order is an interesting idea, although I want better
looking API than

{1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

              matz.

···

In message "Re: OK... :slight_smile: question about hash and array literals" on Mon, 6 Sep 2004 08:50:15 +0900, Bill Guindon <agorilla@gmail.com> writes:

Bill Guindon wrote:
>Personally, I'd like it to remember the order you added things in, use
>that ordering when iterating through the hash, and _optionally_ use it
>for compares.

Matz wrote:

Hmm, I thought hash order would be ignored always for compares.

I would think it would have to, if you don't want to break the semantics
of Hash.

Matz wrote:

Optional use of order is an interesting idea, although I want better
looking API than

> {1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

If you make inspect (for example) respect the insertion order then you
have

    {1=>2, 3=>4}.inspect != {3=>4, 1=>2}.inspect

which is at least a little less obtrusive.

It may, however, be better to have an additional class (OrderedHash, for
want of a much needed better name), in which order was respected for
both comparison and iteration.

My main concern is that just making regular hashes respect insertion
order for iteration but not comparison isn't exactly "least surprise";
so far as I know, the iteration order of hashes presently is arbitrary
but not random. In other words, for any two collections (arrays,
hashes, whatever) it is presently true that:

    a == b

implies

    a.collect { |x| x } == b.collect { |x| x }

but this would no longer be true.

Of course, this line of argument would be weakened if the implication
isn't true at present for hashes.

My preferred answer is to make => an operator that takes two object and
returns a hash in any context (assuming of course that the precedence
issues this raises could by resolved). That would let people define
their own extension to hash that worked however they wanted.

Or (even better in my book) make anything that matches

      /[:+-=<>|*&^%?~!._]{2,6}/

or some such available as an operator (and thus, the vast majority of
them would be up for grabs for tasks such as this). Precedence &
associativity could be assigned by some convention (all equal, longer
things lower, or...?) or (though I'm not sure how it could be
implemented) user defined.

It would require a trick sort of like what is used for tOP_ASGN to keep
the parser from exploding (over 8000000 new operators? Yikes!) but I
think it might work.

To Hal: would a notation like

     ordered_hash(1-->2,3-->4,...)

or

     1-->2 | 3-->4 | ....

suit you (the latter assuming the precedence could be controlled or the
conventions were fortuitous)?

-- MarkusQ

this is a GREAT idea! i've always thought that there is no reason hashes
could not simply remember the order of inserts and use it. as far as
comparisons i would agree they should not be ordered in general, perhaps

   hash.identical other

or something that did depend on order. one of the coolest things about
ordered hashes would be their use with yaml! i use yaml configs and the lack
of hash ordering is a constant pain in my side. how difficult do you think it
would be to add order memory for hash insert operations and to use it for
each/map, etc.?

-a

···

On Mon, 6 Sep 2004, Yukihiro Matsumoto wrote:

Hi,

In message "Re: OK... :slight_smile: question about hash and array literals" > on Mon, 6 Sep 2004 08:50:15 +0900, Bill Guindon <agorilla@gmail.com> writes:

>Personally, I'd like it to remember the order you added things in, use
>that ordering when iterating through the hash, and _optionally_ use it
>for compares.

Hmm, I thought hash order would be ignored always for compares.
Optional use of order is an interesting idea, although I want better
looking API than

> {1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

              matz.

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

How about { 1=>2, 3=>4 } !~ { 3=>4, 1=>2 }
          { 1=>2, 3=>4 } =~ { 1=>2, 3=>4 }

OTOH, that syntax might more profitably be reserved for pattern
matching, which would also be a nice thing to have.

martin

···

Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hmm, I thought hash order would be ignored always for compares.
Optional use of order is an interesting idea, although I want better
looking API than

> {1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

Martin DeMello wrote:

Hmm, I thought hash order would be ignored always for compares.
Optional use of order is an interesting idea, although I want better
looking API than

{1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

How about { 1=>2, 3=>4 } !~ { 3=>4, 1=>2 }
          { 1=>2, 3=>4 } =~ { 1=>2, 3=>4 }

OTOH, that syntax might more profitably be reserved for pattern
matching, which would also be a nice thing to have.

I am not especially worried about testing equality with or without
order.

In nearly five years of Ruby, I cannot recall ever comparing two
hashes for equality at all.

But if I could have guaranteed order in hash literals and insertion
order preserved in general, I would be very happy.

More than half the code I have written would benefit from that in
some small way (including where I use YAML).

Hal

···

Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Sounds like a new data type to me. I frequently find myself doing
things like this:

    @some_data_by_index = Hash.new
    @some_data_order = Array.new

and then I manage the two variables together for any insertion I make
into the data:

    @some_data_by_index[value.key] = value
    @some_data_order.push value

So what if there was an ArrayAndHash?

    @some_data = ArrayAndHash.new(:key)
    @some_data.push value

Such a thing would need some semantics of both an Array and a Hash, and
I don't feel like figuring out what they should look like right now.
Maybe next time I need such a thing I'll think about it more.

Similar things have been discussed on the list before, but I don't know
if anything became of them.

T\_/T\_/T
Michael H Buselli <eholgnyx@cosine.org>
"If you give a man a phish, he has a stolen credit card for a day. If
you teach a man to phish, he will eat three square meals daily for a
lifetime; perhaps served from behind bars, but he will not go hungry."

···

On Mon, 06 Sep 2004 13:10:12 +0900, Ara.T.Howard@noaa.gov wrote:

On Mon, 6 Sep 2004, Yukihiro Matsumoto wrote:

> Hmm, I thought hash order would be ignored always for compares.
> Optional use of order is an interesting idea, although I want better
> looking API than
>
> > {1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

this is a GREAT idea! i've always thought that there is no reason hashes
could not simply remember the order of inserts and use it. as far as
comparisons i would agree they should not be ordered in general, perhaps

   hash.identical other

or something that did depend on order. one of the coolest things about
ordered hashes would be their use with yaml! i use yaml configs and the lack
of hash ordering is a constant pain in my side. how difficult do you think i
-t
would be to add order memory for hash insert operations and to use it for
each/map, etc.?

[...]

In nearly five years of Ruby, I cannot recall ever comparing two
hashes for equality at all.

[...]

My test cases often use assert_equal on two hashes.

···

In article <413BFD4D.6080101@hypermetrics.com>, Hal Fulton wrote:

database apis may use hashes as tuples so you end up comparing them. this is
also a can where

   a = tuples.first
   b = tuples.last

   a[field] = b[field]

   cmp = a == b

may, or may not, require the notion of insertion order.

-a

···

On Mon, 6 Sep 2004, Hal Fulton wrote:

Martin DeMello wrote:

Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hmm, I thought hash order would be ignored always for compares.
Optional use of order is an interesting idea, although I want better
looking API than

> {1=>2, 3=>4}.ordered != {3=>4, 1=>2}.ordered

How about { 1=>2, 3=>4 } !~ { 3=>4, 1=>2 }
          { 1=>2, 3=>4 } =~ { 1=>2, 3=>4 }

OTOH, that syntax might more profitably be reserved for pattern
matching, which would also be a nice thing to have.

I am not especially worried about testing equality with or without
order.

In nearly five years of Ruby, I cannot recall ever comparing two
hashes for equality at all.

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

this doesn't solve the OP's problem - but it might solve the above nicely:

   jib:~ > cat a.rb
   require 'arrayfields'

   a =
   a.fields =

   %w(zero one two three).each do |field|
     a[field] = a.size
     p a
     p a.fields
   end

   jib:~ > ruby a.rb
   [0]
   ["zero"]
   [0, 1]
   ["zero", "one"]
   [0, 1, 2]
   ["zero", "one", "two"]
   [0, 1, 2, 3]
   ["zero", "one", "two", "three"]

arrayfields has the semantics that, if the fields have ever been set (even to
an empty set), asigning to an unknown field appends.

so i automatically does

   @some_data_by_index[value.key] = value
   @some_data_order.push value

kind regards.

-a

···

On Thu, 9 Sep 2004, Michael H Buselli wrote:

Sounds like a new data type to me. I frequently find myself doing
things like this:

   @some_data_by_index = Hash.new
   @some_data_order = Array.new

and then I manage the two variables together for any insertion I make
into the data:

   @some_data_by_index[value.key] = value
   @some_data_order.push value

So what if there was an ArrayAndHash?

   @some_data = ArrayAndHash.new(:key)
   @some_data.push value

Such a thing would need some semantics of both an Array and a Hash, and
I don't feel like figuring out what they should look like right now.
Maybe next time I need such a thing I'll think about it more.

Similar things have been discussed on the list before, but I don't know
if anything became of them.

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

Im also comparing two hashes.. and often find it hard to do because #default
is set to a lambda method.

···

On Monday 06 September 2004 13:30, Tim Sutherland wrote:

In article <413BFD4D.6080101@hypermetrics.com>, Hal Fulton wrote:
[...]

>In nearly five years of Ruby, I cannot recall ever comparing two
>hashes for equality at all.

[...]

My test cases often use assert_equal on two hashes.

--
Simon Strandgaard

Tim Sutherland wrote:

···

In article <413BFD4D.6080101@hypermetrics.com>, Hal Fulton wrote:
[...]

In nearly five years of Ruby, I cannot recall ever comparing two
hashes for equality at all.

[...]

My test cases often use assert_equal on two hashes.

That makes perfect sense, and is obvious now that you mention it.

Hal