digitalmars.D.bugs - hash lookup make dummy hash entry
- bero (18/18) Feb 08 2005 hash lookup make dummy hash entry
- =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= (6/7) Feb 08 2005 This is a well known bug / behaviour...
- Regan Heath (25/31) Feb 08 2005 I believe this thread (if followed far enough) contains the reasoning:
- Unknown W. Brackets (9/16) Feb 08 2005 Which is why it was changed recently so you can do this:
- Regan Heath (9/17) Feb 08 2005 True. This was a good idea IMO.
- =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= (24/47) Feb 08 2005 By using the "in" operator, in case you care about the difference ?
- Unknown W. Brackets (6/7) Feb 08 2005 I'm afraid that I, apparently unlike you, use associative arrays with
- =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= (4/6) Feb 09 2005 So use "in" to separate between them ? Works just fine.
- Regan Heath (6/11) Feb 09 2005 Yes it works, but it's not 'nice'. You are relegated to using pointers f...
- =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= (11/22) Feb 09 2005 You can still use "in" like in a so called boolean expression,
- Unknown W. Brackets (10/11) Feb 09 2005 Point is, if I do this:
- =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= (15/32) Feb 10 2005 How cute, char's don't get the .init value, but instead just a zero.
- Regan Heath (33/76) Feb 08 2005 Agreed.
- =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= (11/27) Feb 08 2005 Hashes are built-in types in D. Thus they don't need eg. functions,
- Nick (4/8) Feb 09 2005 Would it not be a better solution to have "in" return a bool, and instea...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (15/25) Feb 09 2005 That's how it worked before, although it can't optimize the double
- Regan Heath (10/33) Feb 09 2005 You can do this for all cases where init.value == 'non existant'. In oth...
- =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= (18/50) Feb 09 2005 And they can just use the "in" logic first, and avoid getting .init ?
- Regan Heath (38/84) Feb 09 2005 Yes, but then they have a double lookup.
- =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= (22/63) Feb 09 2005 Nope, like all collections in Java it can *only* handle Objects.
- Regan Heath (14/70) Feb 09 2005 :)
- Carlos Santander B. (6/9) Feb 09 2005 Are you referring to the thread "Q: how to do AA of delegates keyed by
- =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= (3/8) Feb 09 2005 The latest DMD version (0.111, 0.112) is not available in GDC just yet.
- Carlos Santander B. (8/37) Feb 09 2005 Double lookup isn't necessary, as you have shown before.
- Regan Heath (6/33) Feb 09 2005 It's either a double lookup or a pointer for basic types.
- Regan Heath (32/65) Feb 09 2005 I guess I _could_ always use a template:
- Nick (5/8) Feb 09 2005 The Java Hashtable isn't really a good model to follow. It can only stor...
- Ben Hinkle (3/10) Feb 08 2005 I don't think those tricks work anymore. The implementation of AAs chang...
hash lookup make dummy hash entry --- /* hash bug */ int main(char[][] args) { char[][char[]] hash; printf("%d\n",hash.length); hash["foo"] = "foo"; printf("%d\n",hash.length); hash["bar"] = "bar"; printf("%d\n",hash.length); // print 2 char[] val = hash["baz"]; // lookups make ' hash["baz"] = null ' new entry printf("%d\n",hash.length); // print 3 return 0; } --- Both hash lookup and setting generate "_aaGet" function call and set hash[key]=0 when lookup.
Feb 08 2005
bero wrote:hash lookup make dummy hash entryThis is a well known bug / behaviour... You currently need to use the "in" operator: char[] val = "baz" in hash ? hash["baz"] : ""; It's on purpose, but nobody knows why ? --anders
Feb 08 2005
On Tue, 08 Feb 2005 19:43:28 +0100, Anders F Björklund <afb algonet.se> wrote:bero wrote:I believe this thread (if followed far enough) contains the reasoning: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.dtl/124 If you have an AA of 'reference' types then you can return null on a non-existant entry. If you have an AA of 'value' types i.e. int, long, struct then you can't return null, but you can return Type.init, however: how do you tell that apart from a existing entry with that same value? So, either the AA creates an entry, or it throws an exception. Personally I think the latter is the correct default behaviour. Really the only reason not to use "if (x in aa)" all the time is that it in most cases causes a double lookup eg. if (x in aa) { y = aa[x]; ..etc.. } In the thread above I proposed some helper functions to avoid the double lookup and Ben even wrote some of them. bool contains(key_type key, out value_type value); --returns existance of value, assigns 'value' if found bool contains(key_type key, out index_type at); --returns existance of value, assigns 'at' to location which can then be used to get/replace/add an item. Reganhash lookup make dummy hash entryThis is a well known bug / behaviour... You currently need to use the "in" operator: char[] val = "baz" in hash ? hash["baz"] : ""; It's on purpose, but nobody knows why ?
Feb 08 2005
Which is why it was changed recently so you can do this: y = x in aa; if (y) { ... } Which of course is a bit different, but is only a single lookup all the same. -[Unknown]Really the only reason not to use "if (x in aa)" all the time is that it in most cases causes a double lookup eg. if (x in aa) { y = aa[x]; ..etc.. }
Feb 08 2005
On Tue, 08 Feb 2005 12:58:47 -0800, Unknown W. Brackets <unknown simplemachines.org> wrote:Which is why it was changed recently so you can do this: y = x in aa; if (y) { ... } Which of course is a bit different, but is only a single lookup all the same.True. This was a good idea IMO. However, I'm still not convinced the behaviour of aa["key"] for a missing value is 'correct'. It seems to cause bugs, at least for begginners un-used to the behaviour and may even cause the odd problem for the more experienced. That said, I'm not convinced an exception is all that 'nice' either. Regan
Feb 08 2005
Regan Heath wrote:Perfectly alright.I believe this thread (if followed far enough) contains the reasoning: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.dtl/124 If you have an AA of 'reference' types then you can return null on a non-existant entry.hash lookup make dummy hash entryIt's on purpose, but nobody knows why ?If you have an AA of 'value' types i.e. int, long, struct then you can't return null, but you can return Type.init, however: how do you tell that apart from a existing entry with that same value?By using the "in" operator, in case you care about the difference ? In silly languages, like Java's JDBC interface for instance, they have "helper" functions like isNull or wrap primitives in objects. (both of which could still be emulated in D with some extra code)So, either the AA creates an entry, or it throws an exception. Personally I think the latter is the correct default behaviour.It would be perfectly acceptible for the AA to: 1) *not* create something upon reading 2) *not* throw an annoying exception But to just return Type.init and be done with it ? This enables the hashes to work as unlimited arrays, in that they are all inited to the default value but do not throw ArrayBoundsError (since there is none)Really the only reason not to use "if (x in aa)" all the time is that it in most cases causes a double lookup eg. if (x in aa) { y = aa[x]; ..etc.. }Walter changed the language, so that "in" now returns a *pointer* (there are still a few bugs in the new implementation, but anyway) This means you can now do: if ((p = x in aa) != null) { y = *p; } which avoids the double-lookup, at the expense of readability... Just don't try this with function delegates, and a few other AA types. (there you still need the double lookup like above, at least for now)In the thread above I proposed some helper functions to avoid the double lookup and Ben even wrote some of them.Shouldn't be needed, with the new "in" implementation (when debugged) Never mind re-introducing pointers, and mixing booleans and pointers. But the horribly confusing "create entries when reading" should die! Then the only thing left to do is to avoid the "delete" keyword... --anders
Feb 08 2005
I'm afraid that I, apparently unlike you, use associative arrays with many values in them - including some that are Type.init. To have it return Type.init and not create the entry seems much worse to me than just creating the darn thing (which mind you, I don't quite like either.) -[Unknown]But to just return Type.init and be done with it ?
Feb 08 2005
Unknown W. Brackets wrote:I'm afraid that I, apparently unlike you, use associative arrays with many values in them - including some that are Type.init.So use "in" to separate between them ? Works just fine. Or do you mean you actually use hash[key] to set them ? --anders
Feb 09 2005
On Wed, 09 Feb 2005 11:04:29 +0100, Anders F Björklund <afb algonet.se> wrote:Unknown W. Brackets wrote:Yes it works, but it's not 'nice'. You are relegated to using pointers for basic types, that seems contrary to the fact that they're 'basic' types.I'm afraid that I, apparently unlike you, use associative arrays with many values in them - including some that are Type.init.So use "in" to separate between them ? Works just fine.Or do you mean you actually use hash[key] to set them ?I don't follow, why is this an issue? Regan
Feb 09 2005
Regan Heath wrote:You can still use "in" like in a so called boolean expression, like before. Won't matter that it's a pointer now and not bit ? And then use hash[key] to retrieve it. Avoids the pointer, but does mean a double lookup on the hash key is being made. If you want the fast route, just use the pointer for both.Yes it works, but it's not 'nice'. You are relegated to using pointers for basic types, that seems contrary to the fact that they're 'basic' types.I'm afraid that I, apparently unlike you, use associative arrays with many values in them - including some that are Type.init.So use "in" to separate between them ? Works just fine.The bug we're talking about is that when you read hash[key], the value gets set to .init - and unless someone is actually using this "feature", it should be removed from the language. Since it's really confusing and annoying to everyone else... --andersOr do you mean you actually use hash[key] to set them ?I don't follow, why is this an issue?
Feb 09 2005
Point is, if I do this: ... char[int] test; test[4] = 0; return test[5]; ... I DO NOT want 0, because that would only confuse my programming.... that's all I meant. If it has to return 0, it should set that too. Only way that makes sense, imho. -[Unknown]Or do you mean you actually use hash[key] to set them ?
Feb 09 2005
Unknown W. Brackets wrote:Point is, if I do this: ... char[int] test; test[4] = 0; return test[5]; ...How cute, char's don't get the .init value, but instead just a zero. Now, that's.... totally useless:// Not found, create new elem //printf("create new one\n"); e = cast(aaA *) cast(void*) new byte[aaA.sizeof + keysize + valuesize]; memcpy(e + 1, pkey, keysize); e.hash = key_hash; *pe = e;Would have more sense if it was .init ?I DO NOT want 0, because that would only confuse my programming.... that's all I meant. If it has to return 0, it should set that too. Only way that makes sense, imho.Had you gotten a '\xFF', maybe it could have worked for you too ? But if you keep on relying on side effects like that, I guess the current behaviour is working as you like. Either way, calling opIndex on an array with a nonexisting key should be defined and documentated properly. But out of the three "plausible" solutions to what this op should do: 1) return 0 or -1 or null or some odd value like that 2) throw an exception, KeyNotFoundException or whatever 3) silently create a new zero-entry and return it I find the current behaviour (3) to the *most* confusing... --anders
Feb 10 2005
On Tue, 08 Feb 2005 22:04:57 +0100, Anders F Björklund <afb algonet.se> wrote:Regan Heath wrote:Agreed.Perfectly alright.I believe this thread (if followed far enough) contains the reasoning: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.dtl/124 If you have an AA of 'reference' types then you can return null on a non-existant entry.hash lookup make dummy hash entryIt's on purpose, but nobody knows why ?Forcing you to either use a double lookup, or a pointer... it just seems to me like there has to be a better solution, I mean these are basic types after all, my gut feeling is that it should be easy/simple and it's not.If you have an AA of 'value' types i.e. int, long, struct then you can't return null, but you can return Type.init, however: how do you tell that apart from a existing entry with that same value?By using the "in" operator, in case you care about the difference ?In silly languages, like Java's JDBC interface for instance, they have "helper" functions like isNull or wrap primitives in objects. (both of which could still be emulated in D with some extra code)I dislike these wrappers in general.Agreed.So, either the AA creates an entry, or it throws an exception. Personally I think the latter is the correct default behaviour.It would be perfectly acceptible for the AA to: 1) *not* create something upon reading2) *not* throw an annoying exceptionAgreed.But to just return Type.init and be done with it ?This bugs me. I'd rather use a function: bool contains(key_type key, out value_type value); Which: 1. returned 'true' and assigned 'value' to the existing value. 2. returned 'false' and did nothing to 'value'. This works the same way for both reference and value types. I admit it doesn't work for structs, it's the whole "how do you copy a struct?" problem, however I'd argue that in this case it's better to use struct pointers, to avoid copying large blocks of memory. It's not a perfect solution, but it works well, and identically for everything but structs, so it seems the best soln to me.This enables the hashes to work as unlimited arrays, in that they are all inited to the default value but do not throw ArrayBoundsError (since there is none)I don't think they should ever throw 'ArrayBoundsError'. If they throw anything it's 'NoSuchItemError' or something.It's a good solution, but it's not perfect as you say. Readability suffers, and we're forced to use pointers again, something I'm keen to avoid if at all possible.Really the only reason not to use "if (x in aa)" all the time is that it in most cases causes a double lookup eg. if (x in aa) { y = aa[x]; ..etc.. }Walter changed the language, so that "in" now returns a *pointer* (there are still a few bugs in the new implementation, but anyway) This means you can now do: if ((p = x in aa) != null) { y = *p; } which avoids the double-lookup, at the expense of readability... Just don't try this with function delegates, and a few other AA types. (there you still need the double lookup like above, at least for now)I want to avoid re-introducing pointers, my solution does this by using an 'out' variable. I don't understand "mixing booleans and pointers", are you referring to "if (pointer)" statements?In the thread above I proposed some helper functions to avoid the double lookup and Ben even wrote some of them.Shouldn't be needed, with the new "in" implementation (when debugged) Never mind re-introducing pointers, and mixing booleans and pointers.But the horribly confusing "create entries when reading" should die!Agreed.Then the only thing left to do is to avoid the "delete" keyword...Which has some (commonly percieved) odd behaviour all of it's own. Regan
Feb 08 2005
Regan Heath wrote:I'd rather use a function: bool contains(key_type key, out value_type value); Which: 1. returned 'true' and assigned 'value' to the existing value. 2. returned 'false' and did nothing to 'value'. This works the same way for both reference and value types.Hashes are built-in types in D. Thus they don't need eg. functions, or it would be the same as it is implemented in Java Collections ?I don't think they should ever throw 'ArrayBoundsError'. If they throw anything it's 'NoSuchItemError' or something.Doesn't matter, since you still need the double lookup then with "in", to avoid having it throw up all over the place.It's a good solution, but it's not perfect as you say. Readability suffers, and we're forced to use pointers again, something I'm keen to avoid if at all possible.It's also cheerfully mixing those pointers with a boolean "in"Well, compare: delete array[key], for different types of arrays... (dynamic int[] arrays where key is an int, with the associative) I suggested "out" myself. 1) it's a keyword 2) rhymes with "in" (and it could return a pointer to the item that it just removed) --andersThen the only thing left to do is to avoid the "delete" keyword...Which has some (commonly percieved) odd behaviour all of it's own.
Feb 08 2005
Walter changed the language, so that "in" now returns a *pointer* (there are still a few bugs in the new implementation, but anyway) This means you can now do: if ((p = x in aa) != null) { y = *p; } which avoids the double-lookup, at the expense of readability...Would it not be a better solution to have "in" return a bool, and instead have the compiler optimize away the double lookup? I'm no expert, so I don't know if this is even possible. Is it? Nick
Feb 09 2005
Nick wrote:That's how it worked before, although it can't optimize the double lookup since it doesn't know that you are going to use it again... *I* still believe that in most cases you could just have done a: if ((y = aa[x) != y.init) { ... } and totally ignored the difference of whether x was "in" or not ? (it doesn't work with .init entries) You couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ? (Java 2 Map does permit null keys) But you can't at the moment, since that will instead fill the hash up... (you can't do if(y = aa[x)), since "'=' does not give a boolean result") Which means that until the *bugs* has been addressed, you need to write: val = key in hash ? hash[key] : val.init; Instead of just: val = hash[key]; --andersWalter changed the language, so that "in" now returns a *pointer* (there are still a few bugs in the new implementation, but anyway) This means you can now do: if ((p = x in aa) != null) { y = *p; } which avoids the double-lookup, at the expense of readability...Would it not be a better solution to have "in" return a bool, and instead have the compiler optimize away the double lookup? I'm no expert, so I don't know if this is even possible. Is it?
Feb 09 2005
On Wed, 09 Feb 2005 11:01:17 +0100, Anders F Björklund <afb algonet.se> wrote:Nick wrote:You can do this for all cases where init.value == 'non existant'. In other words when you do not need to treat non existant as different to the init.value. That might be 'most' cases for you, it might not be for someone else.That's how it worked before, although it can't optimize the double lookup since it doesn't know that you are going to use it again... *I* still believe that in most cases you could just have done a: if ((y = aa[x) != y.init) { ... } and totally ignored the difference of whether x was "in" or not ? (it doesn't work with .init entries)Walter changed the language, so that "in" now returns a *pointer* (there are still a few bugs in the new implementation, but anyway) This means you can now do: if ((p = x in aa) != null) { y = *p; } which avoids the double-lookup, at the expense of readability...Would it not be a better solution to have "in" return a bool, and instead have the compiler optimize away the double lookup? I'm no expert, so I don't know if this is even possible. Is it?You couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ?What did it do/return when you requested a non existant element?(Java 2 Map does permit null keys)null keys? or null values?But you can't at the moment, since that will instead fill the hash up... (you can't do if(y = aa[x)), since "'=' does not give a boolean result") Which means that until the *bugs* has been addressed, you need to write: val = key in hash ? hash[key] : val.init; Instead of just: val = hash[key];Are you talking about java above, or D? Regan
Feb 09 2005
Regan Heath wrote:And they can just use the "in" logic first, and avoid getting .init ? Or if they do get a .init (0 or null or whatever), they can check with "in" if it existed as .init or if it didn't exist in the hash. But reading a value should not just create and store a blank one.*I* still believe that in most cases you could just have done a: if ((y = aa[x) != y.init) { ... } and totally ignored the difference of whether x was "in" or not ? (it doesn't work with .init entries)You can do this for all cases where init.value == 'non existant'. In other words when you do not need to treat non existant as different to the init.value. That might be 'most' cases for you, it might not be for someone else.It returned null. If you used null keys, it threw NullPointerExceptions Java 1:You couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ?What did it do/return when you requested a non existant element?Returns: the value to which the key is mapped in this hashtable; null if the key is not mapped to any value in this hashtable.http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.htmlBoth, I believe ? But they reworked the whole Java Collections a *lot*. Java 2:(Java 2 Map does permit null keys)null keys? or null values?Returns the value to which the specified key is mapped in this identity hash map, or null if the map contains no mapping for this key. A return value of null does not necessarily indicate that the map contains no mapping for the key; it is also possible that the map explicitly maps the key to null. The containsKey method may be used to distinguish these two cases.http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.htmlBack in D land, again. :-) No primitive hashes in Java, objects there. And in the current D implementation, reading a nonexisting key will create a new value of .init for the key, and return that. Thus, the need to use "in" - to avoid creating dummy hash entries. I fail to see why one wants a dummy new value or an exception. Maybe someone can give some example code that relies on either ? --andersWhich means that until the *bugs* has been addressed, you need to write: val = key in hash ? hash[key] : val.init; Instead of just: val = hash[key];Are you talking about java above, or D?
Feb 09 2005
On Wed, 09 Feb 2005 23:21:30 +0100, Anders F Björklund <afb algonet.se> wrote:Regan Heath wrote:Yes, but then they have a double lookup.And they can just use the "in" logic first, and avoid getting .init ?*I* still believe that in most cases you could just have done a: if ((y = aa[x) != y.init) { ... } and totally ignored the difference of whether x was "in" or not ? (it doesn't work with .init entries)You can do this for all cases where init.value == 'non existant'. In other words when you do not need to treat non existant as different to the init.value. That might be 'most' cases for you, it might not be for someone else.Or if they do get a .init (0 or null or whatever), they can check with "in" if it existed as .init or if it didn't exist in the hash.A double lookup.But reading a value should not just create and store a blank one.I agree totally, I'm not arguing 'for' this behaviour at all. :) Sorry if I missled.Could it store basic types i.e. 'int'?It returned null.You couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ?What did it do/return when you requested a non existant element?If you used null keys, it threw NullPointerExceptionsSure, I can't really see a point in a null key.Java 1:Thanks.Returns: the value to which the key is mapped in this hashtable; null if the key is not mapped to any value in this hashtable.http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.htmlI can understand null values, why do you want/need null keys?Both, I believe ? But they reworked the whole Java Collections a *lot*.(Java 2 Map does permit null keys)null keys? or null values?Java 2:Thanks.Returns the value to which the specified key is mapped in this identity hash map, or null if the map contains no mapping for this key. A return value of null does not necessarily indicate that the map contains no mapping for the key; it is also possible that the map explicitly maps the key to null. The containsKey method may be used to distinguish these two cases.http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.htmlI know, I disagree with this behaviour.Back in D land, again. :-) No primitive hashes in Java, objects there. And in the current D implementation, reading a nonexisting key will create a new value of .init for the key, and return that.Which means that until the *bugs* has been addressed, you need to write: val = key in hash ? hash[key] : val.init; Instead of just: val = hash[key];Are you talking about java above, or D?Thus, the need to use "in" - to avoid creating dummy hash entries.Sure.I fail to see why one wants a dummy new value or an exception.I don't want the former, I don't want the latter, however if they were our only choices I'd choose the latter. As you've said we have other choices: - use 'in' and pointers. To me that seems contrary to the idea that a basic type is just that basic, eg. int[char[]] aa; int *p; int v; //here we are trying to get the value of "fred" out of the aa without a double lookup. p = ("fred" in aa); v = *p; //not too bad I admit, less verbose than try { v = aa["fred"]; } catch(Exception e) { } Ahhh well, I guess all I'm saying is that: - I dislike the behaviour of v = aa["fred"] when "fred" does not exist, it seems to be the greater of the evils. - I dislike the soln we have to use to avoid a double lookup, but it appears to be the lesser of the evils.Maybe someone can give some example code that relies on either ?Not I. Regan
Feb 09 2005
Regan Heath wrote:<phew>But reading a value should not just create and store a blank one.I agree totally, I'm not arguing 'for' this behaviour at all. :) Sorry if I missled.Nope, like all collections in Java it can *only* handle Objects. That's why they have all the wrapper object types for primitives: Integer, Byte, Short, Long, Character, Float, Double, etc. And of course the String class is the default, for doing strings (doesn't really matter, since char[] is also an object in Java!) For the JDBC interface, they do a double approach: there is one Object-returning method, and one for each of the primitive types - including a boolean "wasNull" function to check for null values. http://java.sun.com/j2se/1.4.2/docs/api/java/sql/ResultSet.html Quite different. (D does *not* want such wrapper classes/methods)Could it store basic types i.e. 'int'?It returned null.You couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ?What did it do/return when you requested a non existant element?"None of the above". :-)I fail to see why one wants a dummy new value or an exception.I don't want the former, I don't want the latter, however if they were our only choices I'd choose the latter.As you've said we have other choices: - use 'in' and pointers.Pointers are optional.To me that seems contrary to the idea that a basic type is just that basic, eg. int[char[]] aa; int *p; int v; //here we are trying to get the value of "fred" out of the aa without a double lookup. p = ("fred" in aa); v = *p; //not too bad I admit, less verbose than try { v = aa["fred"]; } catch(Exception e) { }It doesn't work for all types of p, though. e.g. function delegates.Ahhh well, I guess all I'm saying is that: - I dislike the behaviour of v = aa["fred"] when "fred" does not exist, it seems to be the greater of the evils.Mother of all evils.- I dislike the soln we have to use to avoid a double lookup, but it appears to be the lesser of the evils.For e.g. hashes of strings and Objects, just returning null is fine And that doesn't require a double lookup either... (except for "in") alias char[] str; str[str] aa; str v = aa["fred"]; --anders
Feb 09 2005
On Thu, 10 Feb 2005 00:19:05 +0100, Anders F Björklund <afb algonet.se> wrote:Regan Heath wrote::)<phew>But reading a value should not just create and store a blank one.I agree totally, I'm not arguing 'for' this behaviour at all. :) Sorry if I missled.With that, I agree.Nope, like all collections in Java it can *only* handle Objects. That's why they have all the wrapper object types for primitives: Integer, Byte, Short, Long, Character, Float, Double, etc. And of course the String class is the default, for doing strings (doesn't really matter, since char[] is also an object in Java!) For the JDBC interface, they do a double approach: there is one Object-returning method, and one for each of the primitive types - including a boolean "wasNull" function to check for null values. http://java.sun.com/j2se/1.4.2/docs/api/java/sql/ResultSet.html Quite different. (D does *not* want such wrapper classes/methods)Could it store basic types i.e. 'int'?It returned null.You couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ?What did it do/return when you requested a non existant element?Only if you're dealing with an object, or you don't mind the double lookup, right?"None of the above". :-)I fail to see why one wants a dummy new value or an exception.I don't want the former, I don't want the latter, however if they were our only choices I'd choose the latter.As you've said we have other choices: - use 'in' and pointers.Pointers are optional.I suspect this is a bug.To me that seems contrary to the idea that a basic type is just that basic, eg. int[char[]] aa; int *p; int v; //here we are trying to get the value of "fred" out of the aa without a double lookup. p = ("fred" in aa); v = *p; //not too bad I admit, less verbose than try { v = aa["fred"]; } catch(Exception e) { }It doesn't work for all types of p, though. e.g. function delegates.I agree, however when it comes to generics (i.e. templates accepting AA's of both objects and basic types) you're force to use either a pointer or the double lookup. Or you could write 2 versions of the template and specialise one to AA's of basic types. Not sure you can do this? And it seems contrary to the idea of 'generic' :) ReganAhhh well, I guess all I'm saying is that: - I dislike the behaviour of v = aa["fred"] when "fred" does not exist, it seems to be the greater of the evils.Mother of all evils.- I dislike the soln we have to use to avoid a double lookup, but it appears to be the lesser of the evils.For e.g. hashes of strings and Objects, just returning null is fine And that doesn't require a double lookup either... (except for "in") alias char[] str; str[str] aa; str v = aa["fred"];
Feb 09 2005
Anders F Björklund wrote:It doesn't work for all types of p, though. e.g. function delegates.Are you referring to the thread "Q: how to do AA of delegates keyed by int?"? Because, at least in DMD, it works fine (as I shown in my reply in that thread). _______________________ Carlos Santander Bernal
Feb 09 2005
Carlos Santander B. wrote:The latest DMD version (0.111, 0.112) is not available in GDC just yet. --andersIt doesn't work for all types of p, though. e.g. function delegates.Are you referring to the thread "Q: how to do AA of delegates keyed by int?"? Because, at least in DMD, it works fine (as I shown in my reply in that thread).
Feb 09 2005
Regan Heath wrote:As you've said we have other choices: - use 'in' and pointers. To me that seems contrary to the idea that a basic type is just that basic, eg. int[char[]] aa; int *p; int v; //here we are trying to get the value of "fred" out of the aa without a double lookup. p = ("fred" in aa); v = *p; //not too bad I admit, less verbose than try { v = aa["fred"]; } catch(Exception e) { } Ahhh well, I guess all I'm saying is that: - I dislike the behaviour of v = aa["fred"] when "fred" does not exist, it seems to be the greater of the evils. - I dislike the soln we have to use to avoid a double lookup, but it appears to be the lesser of the evils.Double lookup isn't necessary, as you have shown before. I'm not sure if I really like the current behavior, but I've adjusted to it, so it doesn't bother me much. Now, if someone can come up with a better idea, that'll be even better. And, IMHO, exceptions are not a better idea. _______________________ Carlos Santander Bernal
Feb 09 2005
On Wed, 09 Feb 2005 18:51:53 -0500, Carlos Santander B. <csantander619 gmail.com> wrote:Regan Heath wrote:It's either a double lookup or a pointer for basic types.As you've said we have other choices: - use 'in' and pointers. To me that seems contrary to the idea that a basic type is just that basic, eg. int[char[]] aa; int *p; int v; //here we are trying to get the value of "fred" out of the aa without a double lookup. p = ("fred" in aa); v = *p; //not too bad I admit, less verbose than try { v = aa["fred"]; } catch(Exception e) { } Ahhh well, I guess all I'm saying is that: - I dislike the behaviour of v = aa["fred"] when "fred" does not exist, it seems to be the greater of the evils. - I dislike the soln we have to use to avoid a double lookup, but it appears to be the lesser of the evils.Double lookup isn't necessary, as you have shown before.I'm not sure if I really like the current behavior, but I've adjusted to it, so it doesn't bother me much. Now, if someone can come up with a better idea, that'll be even better. And, IMHO, exceptions are not a better idea.I agree. The current method of avoiding a double lookup is the best I've seen/thought of so far, but I still think it's 'yucky'. Regan
Feb 09 2005
On Thu, 10 Feb 2005 13:11:10 +1300, Regan Heath <regan netwin.co.nz> wrote:On Wed, 09 Feb 2005 18:51:53 -0500, Carlos Santander B. <csantander619 gmail.com> wrote:I guess I _could_ always use a template: In an ideal world it would look like: if (aa.find("regan",v)) writefln("Found: ",v); else writefln("Missing"); That would take: - some sort of type deduction, to remove the !(char[],char[]) - the feature for arrays that allows: void free_fn(char[] a); to be called: char[] a; a.free_fn(); to also work with a template function as I've used. ReganRegan Heath wrote:It's either a double lookup or a pointer for basic types.As you've said we have other choices: - use 'in' and pointers. To me that seems contrary to the idea that a basic type is just that basic, eg. int[char[]] aa; int *p; int v; //here we are trying to get the value of "fred" out of the aa without a double lookup. p = ("fred" in aa); v = *p; //not too bad I admit, less verbose than try { v = aa["fred"]; } catch(Exception e) { } Ahhh well, I guess all I'm saying is that: - I dislike the behaviour of v = aa["fred"] when "fred" does not exist, it seems to be the greater of the evils. - I dislike the soln we have to use to avoid a double lookup, but it appears to be the lesser of the evils.Double lookup isn't necessary, as you have shown before.I'm not sure if I really like the current behavior, but I've adjusted to it, so it doesn't bother me much. Now, if someone can come up with a better idea, that'll be even better. And, IMHO, exceptions are not a better idea.I agree. The current method of avoiding a double lookup is the best I've seen/thought of so far, but I still think it's 'yucky'.
Feb 09 2005
In article <opslx7arol23k2f5 ally>, Regan Heath says...The Java Hashtable isn't really a good model to follow. It can only store objects, not basic types. To store an integer you would have to use the ugly Integer(3) wrapper class. NickYou couldn't store "null" in in the old Java 1 class called Hashtable. Can't say it was ever a big problem ?What did it do/return when you requested a non existant element?
Feb 09 2005
In the thread above I proposed some helper functions to avoid the double lookup and Ben even wrote some of them. bool contains(key_type key, out value_type value); --returns existance of value, assigns 'value' if found bool contains(key_type key, out index_type at); --returns existance of value, assigns 'at' to location which can then be used to get/replace/add an item.I don't think those tricks work anymore. The implementation of AAs changed around dmd-107 or so and my code broke. I took all that stuff out of my libraries now that "in" returns a pointer.
Feb 08 2005