What was the reasoning behind adding an RTE for non-existing
key lookup, does anyone have any memories on that?
I do not remember any discussion about RTE on non-existing key
lookup, but I see this natural. HB_HGET( hHash, xKey ) is a king of
synonym for hHash[ xKey ]. So, if Harbour generates runtime error for:
aArray := {}
? aArray[ 1 ]
it should generate RTE for:
hHash := {=>}
? hHash[ 1 ] // or HB_HGET( hHash, 1 )
What's natural for the array operator is not necessarily
natural for a function call IMO. array operator has some
properties we all know and expect for hashes too, just
for arrays, but such thing don't exist for functions
in general. This could be a differentiating feature between
these two syntaxes, right now they are just duplicate syntax.
I'd like to catch hash access error, but not return NIL and mask it.
If the user do not want generate RTE if key does non-exists, there
are two possible solutions (both of them are from my real life app
development):
1) if it's OK, that hash is extended (missing key added) and default
value is always the same, developer can use auto-add feature. The
missing key will be added to hash using hash's default value.
Hm, I find this extremely unnatural and even dangerous. In fact
I didn't understand the whole fuss about "autoadd" when lengthy
discussion were going on. Now I know what it was all about.
For me it'd be the last thing I want that my hash table
automatically extends with new members _on access_. Maybe this
is normal for other languages, I don't know.
For me autoadd on assign is normal, the rest is just another
way to make language semantics difficult to follow/ambiguous
and programs almost impossible to read.
2) if hash should not be extended or default value is different for
different keys, it had to write:
IF HB_HHASKEY( hHash, xKey )
xResult := hHash[ xKey ]
ELSE
xResult := xDefaultValue
ENDIF
or
SomeFunction( IF(HB_HHASKEY(hHash,Key), hHash[xKey], xDefaultValue) )
And this needs two lookups, which gives it an unnecessary
overhead.
Moreover you need a distinct function just to check the
existence of a key. Ideally hb_HGet( h, k ) != NIL could do
this, and with the third parameter, this would be even better,
doing what you and probably most developers would expect.
I have a dozen expressions like this in my code. About 40% of
HB_HHASKEY() calls in my code are used exactly for this purpose,
i.e. to test if key exists and return default value otherwise.
hHash[ xKey ] expression can not be extended to indicate the
default return value, but HB_HGET() function can easy be extended
and I see this extension useful.
I think that's not the question, but rather if we want to
keep the RTE in hb_HGet() at all.
xhb compatibility is not a concern BTW, because it uses
different function names anyway.
Yes, I would be extension of the existing function. I do not see a
big problems about backward compatibility here. Code using two
parameters version HB_HGET( hHash, xKey ) will be compatible. I
don't think many people currently are using code:
HB_HGET(hHash, xKey, "let's pass some extra params", "to make my
own code", "incompatible with future extensions", .T., {||
__QUIT()}, 123, DATE())
No compatibility concern here. It's just strange to modify
RTE logic based on the existence of a parameter.
(except of course normal case when 'if( ! ISCHAR( 1 ) ) -> RTE')
For sure, Harbour's hash implementation details looks very messy
to me. Management of some xhb heritage is a real burden :(
(see also hb_AIns()/hb_ADel(), logging, .ini files, ...)
Brgds,
Viktor
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour