develooper Front page | perl.perl5.porters | Postings from October 2012

aasign'ing hash with odd number of elements and duplicates

Thread Next
From:
Ruslan Zakirov
Date:
October 7, 2012 13:27
Subject:
aasign'ing hash with odd number of elements and duplicates
Message ID:
CAMOxC8tHVGVC+_kYwrST_CTkZ+OVi9+WKZPQn9bxtv6qRwLQvA@mail.gmail.com
Hi,

Recently sent a patch for aassign that changes how hashes are
assigned. Was asked to write more tests. The only tests that were
missing are for assigning with odd number of elements, so I wrote them
to find a can of worms.

If a hash is assigned with odd number of elements then we get a
warning, but code continues and return values should be maintained.
Simple case:

$ perl -E 'say scalar %h = (1..3)'
1:2:3
$ perl -E 'say scalar(%h = (1..3))'
3

Quite resonable results from the first glance and reproducible since
5.8.9 to blead.

Things get messy with duplicates:

$ perl -e 'print join ":", (%h = (1,2,3,4,1)), "\n"'
1:2:3:4:1:

Older versions produce different result, but it's not important.

If we say that the case without duplicates produces correct and
expected results then result in the last situation should be "3:4:1".
It's important to note that order matters here, it can not be "1:3:4".

Solutions:

1) I've fixed it by completly rewriting hash assignment, but it has
side effect for magic hashes. Original code continiously stores values
each time calling hv_store so duplicates are just overwritten. My
implementation doesn't call hv_store for duplicates, one call for
key/value pairs that should be stored.

2) Other way around is to change what is returned in scalar and list
contexts - inject undef into output stream. This is less intrusive
fix. Code keeps the current complexity, but it means that return value
changes for cases where perl has no bugs, eg first example presented
above will return 1,2,3,undef in list context and 4 in scalar.

3) Keep logic, keep return values and complicate the code to satisfy
the corner case.

I would prefer 1 or 2.

In theory continuous saving can be used in tied hashes, for example to
replace overwriting with pushing.

Second solution, while it breaks backwards compatibility, is very
logical as `@a = (%h = ...);` should be pretty much the same as `%h =
...; @a = %h;`.

Thoughts?

PS: I can provide code/tests on request.

-- 
Best regards, Ruslan.

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About