[End of post moved to the beginning]
Axel Liljencrantz wrote:
On 1/3/06, *Netocrat* <[EMAIL PROTECTED]> wrote:
[when using a combined hash/array datatype, how are string and integer indexes treated?]
String "1" is equivalent to integer 1 (in a shell the difference is not
very pronounced anyhow); both are a key that maps to a value.  If
treating the hash as an array, conceptually that key is the first
element, but practically (internal representation) it could be located
anywhere.  Where's the problem?

The problem that I can see is all the potential inconsistency when silently moving from array to map.

[I've converted prompts from ">" to "fish> " to prevent quoting display problems]
fish> #create array
fish> set arr foo bar baz
fish> echo $arr
foo bar baz
fish> #Use it as a map
fish> set arr[smurf] blue
fish> echo $arr
1 2 3 smurf

Not 100% intuitive, IMO.

Agreed; I've instead been envisaging it as:

fish> echo $arr
foo bar baz blue

to be compatible with current array semantics. Then I'm suggesting that a get-keys operator (e.g. @), would result in what you wrote above:

fish> echo @arr
1 2 3 smurf

So "echo [EMAIL PROTECTED]" would have the same output as "echo $arr".

John's response to Axel's example was bafflement, and he writes:
I must not really understand Netocrat's suggestion at all
to which I say: as far as I can tell your understanding is correct.

[using [] as indexing operators for a combined hash/array data type and thus avoiding a new type as well as being backwards compatible with existing fish arrays]
That is indeed the main advantage of the [] map syntax. And it is a very important one, what with my obsession with small syntaxes. :)

On the other hand, the {} map syntax also has some advantages.

* No potentially weird/unintuitive corner cases when creating an array and converting it to a map

Responded to further down.

* No issues with exporting variables to other programs

Would you accept a rephrasing as "No additional issues..."?

* Easy to implement

Agreed, a naive (i.e. non-indexed) implementation is easy.

Do you want fish to support indexed hashes? If so, then a combined hash/array data type is actually easier - John's suggestion implies additional synchronisation/mapping issues: duplicate "keys" are possible in the array representation of the hash but the array=>hash=>array conversion must preserve array indexes for sane use. Since drafting this post I've read John's response, in which he acknowledges this problem and suggests a solution:
Of course you don't have to promise that the
original semantics will be preserved, which would solve that problem
at, I think, a fairly minor cost, since most users probably won't
be using the same variable both ways anyway.  But it would be
conceptually nice if the naive semantics could be preserved.

Sure, that works, but by writing "most users probably won't be using the same variable both ways" you seem to be acknowledging what I wrote previously - that this is an infrequently used mapping. So when using indexed hashes, there's no reason to retain the mapping given that it results in "broken promises" - you might as well have two separate datatypes, array and hash. And in that case, the consolidation offered by the combination type is compelling given that it's possible to design such a type without loss of hash or array functionality, as detailed below.

[much snippage, then...
echo $a where $a is a "sparse array"]
The 'missing' elements become empty elements, i.e. each one of them contains the empty string.

OK, so actually sparse arrays /aren't/ supported by fish, contrary to the claim in my previous post. "count $sparsearray" includes the "missing" elements. Also, explicitly deleting an element shifts all later elements towards the beginning.

This, John has elsewhere responded, is expected behaviour for an array but not for a hash. So first let's see how easy it is to make the current fish array more hash-like in this regard:

Introduce an "unset" symbol for fish's internal representation (in addition to ARRAY_SEP) to differentiate between unset and empty elements (a past list discussion touched on this subject). So we would have:

fish > set -e arr
fish > set arr[10] tenth_el
fish > count $arr
1
fish > echo $arr
tenth_el
fish > echo $arr[9]
fish: Array element at that index is not set
echo $arr[9]
          ^
fish > echo $arr[10]
tenth_el
fish > set arr[9] ""
fish > count $arr
2
fish > echo $arr
 tenth_el # leading space intended
fish > echo $arr[9]

fish > set -e arr[9]
fish > count $arr
1
fish > echo $arr[10]
tenth_el
fish > echo $arr[9]
fish: Array element at that index is not set
echo $arr[9]
          ^

If introducing a combined hash/array type, the error message terms would have alternate wordings: "array element" could also be "map value" or "hash value", and "index" could also be "key".

Elsewhere John's suggested a default value for unset array variables, which would work fine using the above scheme - fish would simply translate the internal "unset" token into the user's default value on expanding/accessing an array. For a combination hash/array datatype this would work in the same manner from a user-perspective (ignoring internal representation for now) and it would simply have no effect on non-integral indices.

John's also defended the current "shift-on-delete" array behaviour:
set $a[1] foo
set $a[2] bar
set $a[3] baz

If you are setting array elements you expect one kind of behavior,
e.g., that if you delete $a[1] then $a[3] becomes undefined, while
$a[1] and $a[2] still exist, but with different values.

OTOH, if you were setting hash elements you would expect a different
behavior: deleting $a[1] would make $a[1] undefined, while $a[2]
and $a[3] still both exist, with their values unchanged.

This is a reasonable argument, because the shift behaviour is useful for implementing fifos. To support it under the dual hash/array variable type, I'd suggest two versions of "set -e" - one that behaves in the "hash" style, and one that behaves in the "array-shift-for-fifos" style where possible - i.e. it decrements the value of the index/key for all immediately consecutive integer indices. So following on from the example above:
fish> set a[10] notconsecutive
fish> set a[foo] notevenconsideredforshifting
fish> set --unset-array-shift-style a[1]
fish> echo $a[1]
bar # shifted
fish> echo $a[2]
baz # shifted
fish> echo $a[10]
notconsecutive # not shifted
fish> echo $a[foo]
notevenconsideredforshifting

So that covers all of the corner cases that immediately come to mind - if anyone can see any others I'm interested to know.

--
http://members.dodo.com.au/~netocrat


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
Fish-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/fish-users

Reply via email to