digitalmars.D - AA question
- bobef (7/7) Apr 08 2005 When I try to read (AA is right of the = ) key that does not exists from...
- Russ Lewis (7/16) Apr 08 2005 You are correct. If you want to check if a given key exists, then use
- bobef (3/19) Apr 08 2005 Yes I know that. But I think new value should be added only on assigment...
- Russ Lewis (5/31) Apr 08 2005 This has been argued extensively before; some people think that it is a
- Georg Wrede (3/40) Apr 08 2005 Let's just say, I'd like to hear the motivations for the current
- Charlie (4/46) Apr 08 2005 I'd like to hear these too , is any one actually _for_ this ?
- Uwe Salomon (14/17) Apr 08 2005 Yes. I am. This is like it's done in Qt, and I think it is quite useful....
- Ben Hinkle (10/26) Apr 09 2005 I think most people here would agree. The question is if [] and "in" are...
- Ben Hinkle (4/6) Apr 09 2005 oops- I meant lvalue. :-P
- Uwe Salomon (37/47) Apr 09 2005 One could discuss about it, yes. But i want to see DMD 1.0, thus i try n...
- Thomas Kuehne (11/18) Apr 09 2005 -----BEGIN PGP SIGNED MESSAGE-----
- Uwe Salomon (4/6) Apr 09 2005 Ah. You know Ultradeutsh? Actually, i use wunschdeutsch in the code
- Ben Hinkle (13/59) Apr 09 2005 It's not a total disaster, true, but if there is a better solution we sh...
- Uwe Salomon (10/17) Apr 09 2005 You couldn't see it before. I uploaded it today and didn't post anything...
- novice2 (5/8) Apr 10 2005 No! "Giving default" if X not exists and "inserting if not exists" are v...
- Uwe Salomon (4/15) Apr 10 2005 Jep, sorry. I meant "lookup X and insert default if X doesn't exist". Th...
- Ben Hinkle (13/27) Apr 10 2005 My preferred AA api, as posted a while ago to Matthew's "in stinks" thre...
- Matthew (20/57) Apr 13 2005 Agree, apart from Value* part
- Ben Hinkle (18/40) Apr 14 2005 I should have been more careful in attributing the different ideas since...
- Matthew (8/37) Apr 14 2005 I'm still feeling a bit unsure, but I always err on the side of strictne...
- Ben Hinkle (59/82) Apr 14 2005 To elaborate on my first reply, to me removing a key that isn't in the a...
- Matthew (29/116) Apr 15 2005 Impishly mixing threads of contention(/contentiousness), I'd say
- =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= (10/22) Apr 10 2005 Do you have any real-life examples of the "give me the value of key X
- Ben Hinkle (5/7) Apr 10 2005 The word-count example at the bottom of the Array doc has something like
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (5/8) Apr 10 2005 I think it would work the same if rvalue defaulted to zero,
- Uwe Salomon (4/7) Apr 10 2005 But ++ (and += and friends) is guaranteed to evaluate the operand only
- =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= (3/9) Apr 10 2005 Maybe it really is broken by design, then. That's too bad...
- Uwe Salomon (7/11) Apr 10 2005 Hm. You are right. Perhaps this should be changed. Everything i needed
- bobef (7/25) Apr 10 2005 It think this behavior is not only *strange* but stupid, I believe, and ...
When I try to read (AA is right of the = ) key that does not exists from AA it gets created. Is this normal? I mean something like this: foo[bar] aa; for bb=aa[bar_that_doesnt_exists_in_the_aa]; And then bb is not null but new foo instead. And is even not new foo because if it is class and I read from it program crashes...
Apr 08 2005
You are correct. If you want to check if a given key exists, then use the expression: <key> in <variable> which returns a pointer. If the key does NOT exist, then it returns null and the key is NOT added to the array. But if the key exists, then it returns a pointer to the value. bobef wrote:When I try to read (AA is right of the = ) key that does not exists from AA it gets created. Is this normal? I mean something like this: foo[bar] aa; for bb=aa[bar_that_doesnt_exists_in_the_aa]; And then bb is not null but new foo instead. And is even not new foo because if it is class and I read from it program crashes...
Apr 08 2005
Yes I know that. But I think new value should be added only on assigment... Am I wrong? And if I do why? In article <d36jna$3cs$1 digitaldaemon.com>, Russ Lewis says...You are correct. If you want to check if a given key exists, then use the expression: <key> in <variable> which returns a pointer. If the key does NOT exist, then it returns null and the key is NOT added to the array. But if the key exists, then it returns a pointer to the value. bobef wrote:When I try to read (AA is right of the = ) key that does not exists from AA it gets created. Is this normal? I mean something like this: foo[bar] aa; for bb=aa[bar_that_doesnt_exists_in_the_aa]; And then bb is not null but new foo instead. And is even not new foo because if it is class and I read from it program crashes...
Apr 08 2005
This has been argued extensively before; some people think that it is a good idea; others do not. Frankly, I'm not too up-to-speed on the exact reasoning, but you should be able to search the newsgroup for info. Anybody have a link, or a message name? bobef wrote:Yes I know that. But I think new value should be added only on assigment... Am I wrong? And if I do why? In article <d36jna$3cs$1 digitaldaemon.com>, Russ Lewis says...You are correct. If you want to check if a given key exists, then use the expression: <key> in <variable> which returns a pointer. If the key does NOT exist, then it returns null and the key is NOT added to the array. But if the key exists, then it returns a pointer to the value. bobef wrote:When I try to read (AA is right of the = ) key that does not exists from AA it gets created. Is this normal? I mean something like this: foo[bar] aa; for bb=aa[bar_that_doesnt_exists_in_the_aa]; And then bb is not null but new foo instead. And is even not new foo because if it is class and I read from it program crashes...
Apr 08 2005
Russ Lewis wrote:This has been argued extensively before; some people think that it is a good idea; others do not. Frankly, I'm not too up-to-speed on the exact reasoning, but you should be able to search the newsgroup for info. Anybody have a link, or a message name?Let's just say, I'd like to hear the motivations for the current behavior (again)!bobef wrote:Yes I know that. But I think new value should be added only on assigment... Am I wrong? And if I do why? In article <d36jna$3cs$1 digitaldaemon.com>, Russ Lewis says...You are correct. If you want to check if a given key exists, then use the expression: <key> in <variable> which returns a pointer. If the key does NOT exist, then it returns null and the key is NOT added to the array. But if the key exists, then it returns a pointer to the value. bobef wrote:When I try to read (AA is right of the = ) key that does not exists from AA it gets created. Is this normal? I mean something like this: foo[bar] aa; for bb=aa[bar_that_doesnt_exists_in_the_aa]; And then bb is not null but new foo instead. And is even not new foo because if it is class and I read from it program crashes...
Apr 08 2005
Let's just say, I'd like to hear the motivations for the current behavior (again)!I'd like to hear these too , is any one actually _for_ this ? Charlie "Georg Wrede" <georg.wrede nospam.org> wrote in message news:4257003D.3030706 nospam.org...Russ Lewis wrote:This has been argued extensively before; some people think that it is a good idea; others do not. Frankly, I'm not too up-to-speed on the exact reasoning, but you should be able to search the newsgroup for info. Anybody have a link, or a message name?Let's just say, I'd like to hear the motivations for the current behavior (again)!bobef wrote:Yes I know that. But I think new value should be added only on assigment... Am I wrong? And if I do why? In article <d36jna$3cs$1 digitaldaemon.com>, Russ Lewis says...You are correct. If you want to check if a given key exists, then use the expression: <key> in <variable> which returns a pointer. If the key does NOT exist, then it returns null and the key is NOT added to the array. But if the key exists, then it returns a pointer to the value. bobef wrote:When I try to read (AA is right of the = ) key that does not exists from AA it gets created. Is this normal? I mean something like this: foo[bar] aa; for bb=aa[bar_that_doesnt_exists_in_the_aa]; And then bb is not null but new foo instead. And is even not new foo because if it is class and I read from it program crashes...
Apr 08 2005
Yes. I am. This is like it's done in Qt, and I think it is quite useful. There are two operators for AAs: [] - insert (+retrieve) value in - test (+retrieve) value As you can see, there already is an operator for looking up a value (it returns a pointer to the value, i think, or null if it isn't in the AA). So you can change it if it is found, without looking it up again. If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map". It is very important to have an operator for every of these use-cases, because all workarounds are much slower and would thus render the AA useless for programmers needing the speed. Ciao uweLet's just say, I'd like to hear the motivations for the current behavior (again)!I'd like to hear these too , is any one actually _for_ this ?
Apr 08 2005
In article <opsoxq1ipy6yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...I think most people here would agree. The question is if [] and "in" are those operators. I had always assumed C++ inserts on [] because it returns a reference for either lvalue or rvalue contexts. In D the compiler detects the most common rvalue context (opIndexAssign) and we can have [] insert in that case and not insert otherwise. I had made a few posts about why inserting on lookup can be bad: it prevents properties from returning an AA (properties can return dynamic arrays just fine) and it makes concurrent AAs use a different API since changing the container on lookup is a big no-no for multi-threaded apps.Yes. I am. This is like it's done in Qt, and I think it is quite useful. There are two operators for AAs: [] - insert (+retrieve) value in - test (+retrieve) value As you can see, there already is an operator for looking up a value (it returns a pointer to the value, i think, or null if it isn't in the AA). So you can change it if it is found, without looking it up again. If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map". It is very important to have an operator for every of these use-cases, because all workarounds are much slower and would thus render the AA useless for programmers needing the speed.Let's just say, I'd like to hear the motivations for the current behavior (again)!I'd like to hear these too , is any one actually _for_ this ?
Apr 09 2005
In D the compiler detects the most common rvalue context (opIndexAssign)oops- I meant lvalue. :-P To make this post more interesting, though, let me toss in a URL: http://www.planetfall.pwp.blueyonder.co.uk/notcpp.html the section about lvalues and operator overloading.
Apr 09 2005
I think most people here would agree. The question is if [] and "in" are those operators.One could discuss about it, yes. But i want to see DMD 1.0, thus i try not to request any new features or changes in the language. This solutions works, and it's not a bad solution. By the way, is there an opLookup() or something else to overload the "in" operator?In D the compiler detects the most common rvalue context (opIndexAssign) and we can have [] insert in that case and not insert otherwise.You mean if you write your own associative container, you would write opIndex() to *not* insert the lookup-value? Hm, i think it's better to provide a member function doing that (if there is no opLookup), to make the use consistent.it prevents properties from returning an AA (properties can return dynamic arrays just fine)I don't understand that. You mean a function like that is not possible: struct SomeStruct { int[char[]] property() { return something; } } void func() { SomeStruct struc; printf("%i\n", struc.property["name"]); }and it makes concurrent AAs use a different API since changing the container on lookup is a big no-no for multi-threaded apps.Well, i would rather change the api to reflect that. Don't provide opIndex[] for concurrent AAs. By the way, i like the implementation of your MinTL very much. I have written a "vector" container which provides full Qt, STL and D API (except the buggy opCmp/opEqual, they are commented out), and handles the memory management for himself. If someone is interested: http://www.uwesalomon.de/code/vector.d (doc is doxygen, but i didn't generate it. General explanation beginning in line 248. But it's like Qt.) http://www.uwesalomon.de/code/global.d (needed as well.) I will write some other containers as i need them, at least a linked list and a map (perhaps a red/tree-map as well to learn the algorithm). Is there a need for the full set of Qt containers (Vector, List, LinkedList, Map, HashMap; perhaps VarLengthArray)? That would make me implement them all... Ciao uwe
Apr 09 2005
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Uwe Salomon schrieb am Sat, 09 Apr 2005 18:26:12 +0200:By the way, i like the implementation of your MinTL very much. I have written a "vector" container which provides full Qt, STL and D API (except the buggy opCmp/opEqual, they are commented out), and handles the memory management for himself. If someone is interested: http://www.uwesalomon.de/code/vector.d (doc is doxygen, but i didn't generate it. General explanation beginning in line 248. But it's like Qt.) http://www.uwesalomon.de/code/global.d (needed as well.)"Implementirung. Operazionen. Konstrukzion/destrukzion." I've never seen Ultradeutsh before :P Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCWA2I3w+/yD4P9tIRAoDtAJ4mMVXLKaC6Tbf7Fb9+3tHKoMk7RwCghgP0 lIJozj8tX0OgboOYqbd6j+o= =h0Uz -----END PGP SIGNATURE-----
Apr 09 2005
"Implementirung. Operazionen. Konstrukzion/destrukzion." I've never seen Ultradeutsh before :PAh. You know Ultradeutsh? Actually, i use wunschdeutsch in the code comments... But perhaps this is a bit OT here ;o) Ciao uwe
Apr 09 2005
In article <opsoy3xye46yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...It's not a total disaster, true, but if there is a better solution we should find it before 1.0 otherwise the bar goes way up for changing behavior IMO.I think most people here would agree. The question is if [] and "in" are those operators.One could discuss about it, yes. But i want to see DMD 1.0, thus i try not to request any new features or changes in the language. This solutions works, and it's not a bad solution.By the way, is there an opLookup() or something else to overload the "in" operator?no. In my code I've been using opIn as a placeholder.I'm saying we don't have to follow the C++ model due to language behaviors. The D language can allow us to change [] in an rvalue context to not insert. In C++ it must insert - there's basically no choice.In D the compiler detects the most common rvalue context (opIndexAssign) and we can have [] insert in that case and not insert otherwise.You mean if you write your own associative container, you would write opIndex() to *not* insert the lookup-value? Hm, i think it's better to provide a member function doing that (if there is no opLookup), to make the use consistent.correct. If property returned a dynamic array the code struc.property["name"] would be ok. With AAs it is not.it prevents properties from returning an AA (properties can return dynamic arrays just fine)I don't understand that. You mean a function like that is not possible: struct SomeStruct { int[char[]] property() { return something; } } void func() { SomeStruct struc; printf("%i\n", struc.property["name"]); }eek. That's a very convenient syntax that I think users would be sad to see unsupported.and it makes concurrent AAs use a different API since changing the container on lookup is a big no-no for multi-threaded apps.Well, i would rather change the api to reflect that. Don't provide opIndex[] for concurrent AAs.By the way, i like the implementation of your MinTL very much. I have written a "vector" container which provides full Qt, STL and D API (except the buggy opCmp/opEqual, they are commented out), and handles the memory management for himself. If someone is interested: http://www.uwesalomon.de/code/vector.d (doc is doxygen, but i didn't generate it. General explanation beginning in line 248. But it's like Qt.) http://www.uwesalomon.de/code/global.d (needed as well.) I will write some other containers as i need them, at least a linked list and a map (perhaps a red/tree-map as well to learn the algorithm). Is there a need for the full set of Qt containers (Vector, List, LinkedList, Map, HashMap; perhaps VarLengthArray)? That would make me implement them all...Cool! I hadn't seen this code before. Maybe I just missed it but I would post an announcement to the D.announce and/or the D.dtl groups.
Apr 09 2005
You couldn't see it before. I uploaded it today and didn't post anything anywhere except this message. But after finishing the list i will post in D.announce. Anywhere else i should write something? In the Wiki? (You see, i'm not very experienced with "open source development" :o). Ah, if you like you can incorporate the vector in your library (if that's possible and feasible). I did some benchmarking with appending a lot of elements one after the other, and it is quite a bit faster than temporarily increasing the length to avoid reallocations. Ciao uwehttp://www.uwesalomon.de/code/vector.d (doc is doxygen, but i didn't generate it. General explanation beginning in line 248. But it's like Qt.) http://www.uwesalomon.de/code/global.d (needed as well.)Cool! I hadn't seen this code before. Maybe I just missed it but I would post an announcement to the D.announce and/or the D.dtl groups.
Apr 09 2005
In article <opsoxq1ipy6yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map".No! "Giving default" if X not exists and "inserting if not exists" are very different. Let's reading aa[not_exist_key] give default, but not write any data to AA. This is side effect. After this "in" operator useless. Information about "was element exists in AA" lost.
Apr 10 2005
Jep, sorry. I meant "lookup X and insert default if X doesn't exist". Thus "in" only does a lookup, and "[]" inserts if necessary. Ciao uweIf you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map".No! "Giving default" if X not exists and "inserting if not exists" are very different. Let's reading aa[not_exist_key] give default, but not write any data to AA. This is side effect. After this "in" operator useless. Information about "was element exists in AA" lost.
Apr 10 2005
In article <opso0b4nv26yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...My preferred AA api, as posted a while ago to Matthew's "in stinks" thread: bit opIn(Key key) // possibly return value* instead Value opIndex(Key key) // throws on missing key void opIndexAssign(Value value, Key key) // insert bit contains(Key key, out Value value) void remove(Key key) // ignores missing key Value* insert(Key key) // lookup and insert if not present .. rest as before except "delete" is removed... The functions with name opFoo are for the operators in, [] and []= -Ben ps - it would be nice to hear boo from Walter what chances any changes to AAs have of happening. I have the feeling the chances are around 10% or less.Jep, sorry. I meant "lookup X and insert default if X doesn't exist". Thus "in" only does a lookup, and "[]" inserts if necessary.If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map".No! "Giving default" if X not exists and "inserting if not exists" are very different. Let's reading aa[not_exist_key] give default, but not write any data to AA. This is side effect. After this "in" operator useless. Information about "was element exists in AA" lost.
Apr 10 2005
"Ben Hinkle" <Ben_member pathlink.com> wrote in message news:d3bg60$2n7q$1 digitaldaemon.com...In article <opso0b4nv26yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...Agree, apart from Value* partMy preferred AA api, as posted a while ago to Matthew's "in stinks" thread: bit opIn(Key key) // possibly return value* insteadJep, sorry. I meant "lookup X and insert default if X doesn't exist". Thus "in" only does a lookup, and "[]" inserts if necessary.If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map".No! "Giving default" if X not exists and "inserting if not exists" are very different. Let's reading aa[not_exist_key] give default, but not write any data to AA. This is side effect. After this "in" operator useless. Information about "was element exists in AA" lost.Value opIndex(Key key) // throws on missing keyAgreevoid opIndexAssign(Value value, Key key) // insertAgreebit contains(Key key, out Value value)Agree. (I think it was me that suggested this one, so am bound to agree <g>)void remove(Key key) // ignores missing keyDon't agree with ignoring missing thing, although not 100% about itValue* insert(Key key) // lookup and insert if not presentDon't get this? What get's inserted? Surely it needs a second param, as in <whatever> insert(Key key, Value value): ?? Now, as to <whatever> is, that depends on how you respond to the above question. My suspicion is that you've used Value* so that some can write to it, which I think sucks, I'm afraid. I really don't think D should be flirting with pointers in such cases. Also, what's wrong with the (Key, Value) syntax?.. rest as before except "delete" is removed...Agree-Ben ps - it would be nice to hear boo from Walter what chances any changes to AAs have of happening.Seconded.I have the feeling the chances are around 10% or less.Optimist!
Apr 13 2005
my preference, too. I haven't thought too hard about use cases for the value* form.My preferred AA api, as posted a while ago to Matthew's "in stinks" thread: bit opIn(Key key) // possibly return value* insteadAgree, apart from Value* partI should have been more careful in attributing the different ideas since my saying "my preferred API" implicitly means I came up with the API, which isn't right.Value opIndex(Key key) // throws on missing keyAgreevoid opIndexAssign(Value value, Key key) // insertAgreebit contains(Key key, out Value value)Agree. (I think it was me that suggested this one, so am bound to agree <g>)I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.void remove(Key key) // ignores missing keyDon't agree with ignoring missing thing, although not 100% about itI have a feeling Walter likes the current behavior because of the example in the Array section with the magic line count[word]++; And so I wanted to supply something similar and the best way I could see was "insert": (*count.insert(word))++ A better name would help. I thought of calling it insertKey but then I shortened it to just insert, perhaps by mistake. Having insert take a key and value makes it the effectively the same as opIndexAssign, which seems redundant. If you scroll up you'll see I put the comment "// insert" next to opIndexAssign so arguably this "insert" name needs to change.Value* insert(Key key) // lookup and insert if not presentDon't get this? What get's inserted? Surely it needs a second param, as in <whatever> insert(Key key, Value value): ?? Now, as to <whatever> is, that depends on how you respond to the above question. My suspicion is that you've used Value* so that some can write to it, which I think sucks, I'm afraid. I really don't think D should be flirting with pointers in such cases. Also, what's wrong with the (Key, Value) syntax?
Apr 14 2005
It was no problem. Just yanking ya chain. ;)I should have been more careful in attributing the different ideas since my saying "my preferred API" implicitly means I came up with the API, which isn't right.bit contains(Key key, out Value value)Agree. (I think it was me that suggested this one, so am bound to agree <g>)I'm still feeling a bit unsure, but I always err on the side of strictness. If people aren't too tired by now, I'd be interested in hearing thoughts on the matter.I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.void remove(Key key) // ignores missing keyDon't agree with ignoring missing thing, although not 100% about itOk. Maybe we need to have code samples / use cases for all the proposed syntax? (I'm such a dumb ass, as I really need to see code in order to think about it <g>) I just have a really bad feeling about pointers being anywhere in the syntax for D for things that do not directly pertain to talking to C APIs. Otherwise, why don't we just drop the ambiguities that come with references, go with pointers for objects, and clear up the identity/equality issue? <g>I have a feeling Walter likes the current behavior because of the example in the Array section with the magic line count[word]++; And so I wanted to supply something similar and the best way I could see was "insert": (*count.insert(word))++ A better name would help. I thought of calling it insertKey but then I shortened it to just insert, perhaps by mistake. Having insert take a key and value makes it the effectively the same as opIndexAssign, which seems redundant. If you scroll up you'll see I put the comment "// insert" next to opIndexAssign so arguably this "insert" name needs to change.Value* insert(Key key) // lookup and insert if not presentDon't get this? What get's inserted? Surely it needs a second param, as in <whatever> insert(Key key, Value value): ?? Now, as to <whatever> is, that depends on how you respond to the above question. My suspicion is that you've used Value* so that some can write to it, which I think sucks, I'm afraid. I really don't think D should be flirting with pointers in such cases. Also, what's wrong with the (Key, Value) syntax?
Apr 14 2005
To elaborate on my first reply, to me removing a key that isn't in the array is similar to closing a stream that is already closed. I see both situations as no-ops since the requested end-state is already satisfied. The basic principle is "no harm no foul". I'd be interesting in more opinions, too, though.I'm still feeling a bit unsure, but I always err on the side of strictness. If people aren't too tired by now, I'd be interested in hearing thoughts on the matter.I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.void remove(Key key) // ignores missing keyDon't agree with ignoring missing thing, although not 100% about itHere's the API with more details/examples. The array is variable "x", the key "key" and the value "val". function: bit opIn(Key key) example: if (key in x) {...} Returns true iff key is in x. function: Value opIndex(Key key) (note this is internal to the compiler impl and isn't user visible) example: val = x[key]; Lookup and return the value for key. Throws an exeption if key is not in x. Result is not an lvalue. function: void opIndexAssign(Value val, Key key) (compiler internal impl) example: x[key] = val; Associates val with key. Inserts if key is not in x and otherwise overwrites previous value. This is the only syntax where x[key] can be used as an lvalue. function: bit contains(Key key, out Value val) example: if (x.contains(key,val)) {...} Returns true iff key is in x. If key is in x assigns the associated value to val. function: void remove(Key key) example: x.remove(key); Removes key from x if key is in x. function: Value* insert(Key key) examples: (*x.insert(key)) += 10; foo(*x.insert(key)) // where foo is void foo(out Value val); If key is in x returns a pointer to the associated value and otherwise insert key with the default value and return a pointer to it. Note that x[key] = value is equivalent to *x.insert(key) = value; I'm tempted to add some more like Value replace(Key key, Value value) Value* query(Key key) // return null if key not in x but I'll hold off on those. They would be nice to have IMO. The reason for adding more sophisticated functions for AAs than dynamic arrays is that writing multiple lookups for AA is significantly more expensive for performance than dynamic arrays.Ok. Maybe we need to have code samples / use cases for all the proposed syntax? (I'm such a dumb ass, as I really need to see code in order to think about it <g>)Value* insert(Key key) // lookup and insert if not presentDon't get this? What get's inserted? Surely it needs a second param, as in <whatever> insert(Key key, Value value):I just have a really bad feeling about pointers being anywhere in the syntax for D for things that do not directly pertain to talking to C APIs. Otherwise, why don't we just drop the ambiguities that come with references, go with pointers for objects, and clear up the identity/equality issue? <g>Exposing the pointer would only happen when you can't use the x[key]=value syntax. The "advanced maneuver" of inserting, initializing and returning an lvalue needs to be possible and that's where the pointers/references come in. If D had references or out-references or whatever then I agree it probably would be nice to remove the pointer stuff. Or if D had a different syntax than x[key] for indicating it should return an lvalue that would work, too.
Apr 14 2005
"Ben Hinkle" <bhinkle mathworks.com> wrote in message news:d3lulk$11pd$1 digitaldaemon.com...Impishly mixing threads of contention(/contentiousness), I'd say that if it's part of the contract of remove(), then there's no problem. ;)To elaborate on my first reply, to me removing a key that isn't in the array is similar to closing a stream that is already closed. I see both situations as no-ops since the requested end-state is already satisfied. The basic principle is "no harm no foul". I'd be interesting in more opinions, too, though.I'm still feeling a bit unsure, but I always err on the side of strictness. If people aren't too tired by now, I'd be interested in hearing thoughts on the matter.I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.void remove(Key key) // ignores missing keyDon't agree with ignoring missing thing, although not 100% about itTotally agreeHere's the API with more details/examples. The array is variable "x", the key "key" and the value "val". function: bit opIn(Key key) example: if (key in x) {...} Returns true iff key is in x.Ok. Maybe we need to have code samples / use cases for all the proposed syntax? (I'm such a dumb ass, as I really need to see code in order to think about it <g>)Value* insert(Key key) // lookup and insert if not presentDon't get this? What get's inserted? Surely it needs a second param, as in <whatever> insert(Key key, Value value):function: Value opIndex(Key key) (note this is internal to the compiler impl and isn't user visible) example: val = x[key]; Lookup and return the value for key. Throws an exeption if key is not in x. Result is not an lvalue.Totally agree.function: void opIndexAssign(Value val, Key key) (compiler internal impl) example: x[key] = val; Associates val with key. Inserts if key is not in x and otherwise overwrites previous value. This is the only syntax where x[key] can be used as an lvalue.Totally agreefunction: bit contains(Key key, out Value val) example: if (x.contains(key,val)) {...} Returns true iff key is in x. If key is in x assigns the associated value to val.Agree, except I think there should also be an overload that doesn't take the out value, i.e. is just a method-form equivalent to "in"function: void remove(Key key) example: x.remove(key); Removes key from x if key is in x.Totally agreefunction: Value* insert(Key key) examples: (*x.insert(key)) += 10; foo(*x.insert(key)) // where foo is void foo(out Value val); If key is in x returns a pointer to the associated value and otherwise insert key with the default value and return a pointer to it. Note that x[key] = value is equivalent to *x.insert(key) = value;Don't like it, I'm afraid. Been reading up on some more 'advanced' Python recently, and the use of * there seems exceedingly foreign and hacky. This gives me the very same impression. I respectfully submit that both your examples syntactically suck. I see where you're coming from, though, which I'd not done earlier in the thread. What you're looking for is how to support a somewhat-analoguous behaviour for other operations as exists for []=. In C++ we'd return a reference from insert() and it'd be simple. Do I rightly recall recent calls for returning lvalues from functions? If so, that'd be the right approach. If not, I think your *-hack is kind of sticking plaster on a deeper inadequacy in D. I feel/hope that there's a solution to the wider issue, but nothing's coming to mind at the moment. I suggest this one is marked for further discussion.I'm tempted to add some more like Value replace(Key key, Value value) Value* query(Key key) // return null if key not in x but I'll hold off on those. They would be nice to have IMO. The reason for adding more sophisticated functions for AAs than dynamic arrays is that writing multiple lookups for AA is significantly more expensive for performance than dynamic arrays.Both interesting. I suspect Walter might have one of his inspirations on this one, if we can sufficiently convince him that the pointer stuff is un appealing.I just have a really bad feeling about pointers being anywhere in the syntax for D for things that do not directly pertain to talking to C APIs. Otherwise, why don't we just drop the ambiguities that come with references, go with pointers for objects, and clear up the identity/equality issue? <g>Exposing the pointer would only happen when you can't use the x[key]=value syntax. The "advanced maneuver" of inserting, initializing and returning an lvalue needs to be possible and that's where the pointers/references come in. If D had references or out-references or whatever then I agree it probably would be nice to remove the pointer stuff. Or if D had a different syntax than x[key] for indicating it should return an lvalue that would work, too.
Apr 15 2005
Uwe Salomon wrote:Do you have any real-life examples of the "give me the value of key X or create and insert a new zero entry for key X and return it to me" ? I know that C++/STL "map" does it that way, just wondered how it would be used in actual code (as I happen to think that it's an ugly bug...) Inserting for lvalues is OK and kinda neat, but inserting for rvalues ? (it would most definitely have to be documented in <blink> tags, or so) And like has been mentioned over and over, it's not even a .init/new - but just a dummy entry full of zeroes ? (just allocated with calloc...) --andersJep, sorry. I meant "lookup X and insert default if X doesn't exist". Thus "in" only does a lookup, and "[]" inserts if necessary.If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map".No! "Giving default" if X not exists and "inserting if not exists" are very different. Let's reading aa[not_exist_key] give default, but not write any data to AA. This is side effect. After this "in" operator useless. Information about "was element exists in AA" lost.
Apr 10 2005
Do you have any real-life examples of the "give me the value of key X or create and insert a new zero entry for key X and return it to me" ?The word-count example at the bottom of the Array doc has something like count[word]++; which only works because the counts are ints and start at 0. Note also no user-defined type could support syntax like that without changing the language somehow (eg by adding references).
Apr 10 2005
Ben Hinkle wrote:The word-count example at the bottom of the Array doc has something like count[word]++; which only works because the counts are ints and start at 0.I think it would work the same if rvalue defaulted to zero, and lvalue inserted the new value ? Assuming that ++ expands to something similar to: "count[word] = count[word] + 1;" ? --anders
Apr 10 2005
I think it would work the same if rvalue defaulted to zero, and lvalue inserted the new value ? Assuming that ++ expands to something similar to: "count[word] = count[word] + 1;" ?But ++ (and += and friends) is guaranteed to evaluate the operand only once... Ciao uwe
Apr 10 2005
Uwe Salomon wrote:Maybe it really is broken by design, then. That's too bad... --andersI think it would work the same if rvalue defaulted to zero, and lvalue inserted the new value ? Assuming that ++ expands to something similar to: "count[word] = count[word] + 1;" ?But ++ (and += and friends) is guaranteed to evaluate the operand only once...
Apr 10 2005
Inserting for lvalues is OK and kinda neat, but inserting for rvalues ? (it would most definitely have to be documented in <blink> tags, or so) And like has been mentioned over and over, it's not even a .init/new - but just a dummy entry full of zeroes ? (just allocated with calloc...)Hm. You are right. Perhaps this should be changed. Everything i needed until now was a function like this: T lookup(Key key, T defaultValue) which returns the value for key or defaultValue if key isn't in the map. No fancy inserting... Ciao uwe
Apr 10 2005
It think this behavior is not only *strange* but stupid, I believe, and it differs from all other [] behavior. If it was normal, [] would be test (+retrieve) value and []= would be insert. It is clear and straight forward... And if it stays this way it should be mentioned with BIG asterix in the docs because it is different from all other D and noone would think it will behave like that... In article <opsoxq1ipy6yjbe6 sandmann.maerchenwald.net>, Uwe Salomon says...Yes. I am. This is like it's done in Qt, and I think it is quite useful. There are two operators for AAs: [] - insert (+retrieve) value in - test (+retrieve) value As you can see, there already is an operator for looking up a value (it returns a pointer to the value, i think, or null if it isn't in the AA). So you can change it if it is found, without looking it up again. If you would change the behaviour of [], there would be no operator for "give me the value to key X, or the default if there isn't an X in the map". It is very important to have an operator for every of these use-cases, because all workarounds are much slower and would thus render the AA useless for programmers needing the speed. Ciao uweLet's just say, I'd like to hear the motivations for the current behavior (again)!I'd like to hear these too , is any one actually _for_ this ?
Apr 10 2005