
*** What is your evaluation of the design? Overall, the design seems sound. I didn't look at every aspect of the design in my review, but the usage seems straightforward, and as the end-goal, I think it passes. It's too bad that you have to specify the type of the member when using member<>, but I don't see a way to infer it without having measurable runtime overhead. The range() member is very clever and is a good use case for Boost.Lambda, IMO. It seems to me that modify() need not have the destructive policy that it does. It appears that modify() erases the node from the index, then reinserts it into the appropriate place. However, it seems to me that modify() could first look to see if the modified node already exists, save the iterator to the correct insertion point, and then only unlink the node if the modification would be succesful. So the strategy would be like this: 1) Change the modifier function object to require a value() member that gives the new value to be used. 2) Instead of calling mod() right away, call something like lower_bound(), using mod.value(). Save the iterator if there isn't already an element there that conflicts. 3) Perform the erase as usual, and then do mod(), link2(), etc. Wow, Boost.Lambda looks like a home run, were it not for the fact that directly assigning to members through the set interface is a serious violation of encapsulation. ;) The safe mode and invariant checking are also nice features. Perhaps they could be a guideline or recommended feature for Boost libraries. One thing that I think should be added (though not affecting my vote) is ranked indexes. So just as an index might be unique or non-unique, it can be ranked or not ranked. Ranking gives an index an O(log n) ordinal search. That is, you can search for the ith item according to a certain index in O(log n) time, given an ordered index (obviously, the sequenced indexes would have an O(n) search time). This does change the structure of the nodes, and necessarily makes them bigger for ranked indexes. So it is not a trivial change. However, I am sure that it is doable and would add value to the library. *** What is your evaluation of the implementation? The implementation seems fairly clean, modulo the regular portability hacks. The coding style is tighter than I prefer (w.r.t whitespace) but doesn't affect my opinion of the code itself. It seems that some care has been taken to consider performance issues without necessarily providing the fastest implementation possible. While the use of MPL, Lambda, and Tuples makes the implementation a little fat, this is the kind of compile-time cost that I think is justified by the run-time and code expressivity benefits. Some of the lines are > 80 columns (e.g.: the copyright notice). I don't like the C-style comments, but I don't expect to be modifying the source, so it's not really an issue. I think that BOOST_NO_MEMBER_TEMPLATES should be deprecated. I don't think there's a single supported compiler in the Boost compiler configs that defines this any more. I think checking against BOOST_MSVC6_MEMBER_TEMPLATES is sufficient, but it would be nice to not even have to check against that. I do believe the parts that come from other code need to retain the original copyright. The parts that were inspired by, but not directly derived from, another implementation probably don't need a copyright notice, but should probably give a mention in the copyright, at the least as a matter of professional courtesy. *** What is your evaluation of the documentation? The documentation is very good, except that it could use some very minor editing (which does not affect the clarity or understandability of the documentation). Here is a somewhat minor nitpick. In the tutorial, the index_list is specified as so: (type of index)<[(tag)[,(key extractor)[,(comparison predicate)]]]> (type of index)<[(key extractor)[,(comparison predicate)]]> I would change it to thus: (unique | non_unique)<[(tag)[,(key extractor)[,(comparison predicate)]]]> (unique | non_unique)<[(key extractor)[,(comparison predicate)]]> It would be nice to be able to read through the documentation like a manual. Thus, next links on each page would be appropriate. On the performance page, you state that the tests were performed on a system with 260 KB "RAM memory", running W2K. I'm absolutely certain that is not correct. ;) "256 MB RAM" sounds a lot more likely. Something that I think should be added to the documentation is a concept page that lists the main concepts in IndexedSet and a concept interface a la the SGI STL reference (www.sgi.com/tech/stl). *** What is your evaluation of the potential usefulness of the library? I think the library is very useful and fills an important gap in the STL. I think it would be "complete" if it were to add ranked index support. Then it would be a total replacement of containers like VB's Collection. In particular, I think the key functors alone make it useful, let alone multiple indexes and the like. *** Did you try to use the library? With what compiler? Did you have any problems? I did try very briefly. However, I got blocked by BJam, and didn't take the time to d/l the latest Boost to fix it (assuming it does). I will try to get BJam working later, and if I succeed before the review is over, I will at least run the tests and create a few small test programs myself. *** How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? I read all the documentation except for the reference section, and I spent some time looking over random parts of the code. *** Are you knowledgeable about the problem domain? Yes. I've had need for similar containers and have hand-rolled some solutions. The scope of IndexedSet is impressive without being too feature-bloated. *** Do you think the library should be accepted as a Boost library? Yes, most definitely. *** Naming issues: Here's my take on names, but should not be construed as affecting my vote for inclusion... Namespace: I think too many namespace levels are not helpful. A separate 'container' namespace seems a bit superfluous to me. There is no danger in name clashes within Boost between container libraries and other kinds of libraries that I can see, and I don't see that it provides a significant documentation benefit. I think additional namespace depth is most appropriate for collections of algorithms, where a proliferation of names is more likely to lead to name collisions. Library name: I don't think IndexedSet is so bad, but an alternative that I like is CompositeSet. Then there could be a Composite Sorted Associative Container concept which would support the notion of containers with multiple keys. Then CompositeSet would be a model of Composite Sorted Associative Container. A synonym for Sorted Associative Container could be Simple Sorted Associative Container or Trivial Sorted Associative Container. Indexes: According to the American Heritage Dictionary, Fourth Edition, as channeled by www.dictionary.com, "indexes" is preferred to "indices". Another spelling metric I like to use is Google. According to Google, "indexes" returns 5.8 million hits, while "indices" returns 5.5 million hits. So that's only a 5% difference, but it's statistically significant. ;) I personally think the preferred spelling should be used throughout the documentation, but that's more of a nitpick than a criticism. Anyway, I prefer "ordered index" to "regular index". As far as index types go, I prefer "ordered_unique" to "set_like", due to consistency. I think Ordered Index should be a concept for this library. Key extraction: Leave it in the library. nth_index_type: I don't like the word "nth", personally. I suggest either of the following naming schemes: nth_index_type -> ordinal_index index_type -> named_index | tagged_index nth_index_type -> index_byval | index_bynum index_type -> index_byname | index_bytag Generalize appropriately to the iterator types. update(): Actually, I do prefer "replace()" over "update()", because it does more accurately reflect the operation. As far as header organization goes, I would think of it this way: What are the major features and concepts of the library, and how will they be used separately or together? Organize the headers in a way that allows users to include feature sets as modules. If you have to, create dummy headers that just include sets of headers that are logically dependent so that users can activate a certain feature by including that header. Also, consider the cost of each header. It is worth the extra effort to isolate expensive headers than cheap ones. Other than that, I don't have any particular suggestions. Dave --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.581 / Virus Database: 368 - Release Date: 2/10/2004

Hello David, thanks for the effort of reviewing indexed_set (and seems you made a thorough review indeed!) "David B. Held" ha escrito:
*** What is your evaluation of the design?
[...]
It's too bad that you have to specify the type of the member when using member<>, but I don't see a way to infer it without having measurable runtime overhead.
This is a recurrent request, but afaik noone has come up with a solution.
The range() member is very clever and is a good use case for Boost.Lambda, IMO.
Credit here goes entirely to Pavel, who pushed me to include this memfun --I was reluctant to add non-standard features.
It seems to me that modify() need not have the destructive policy that it does. It appears that modify() erases the node from the index, then reinserts it into the appropriate place. However, it seems to me that modify() could first look to see if the modified node already exists, save the iterator to the correct insertion point, and then only unlink the node if the modification would be succesful.
So the strategy would be like this:
1) Change the modifier function object to require a value() member that gives the new value to be used. 2) Instead of calling mod() right away, call something like lower_bound(), using mod.value(). Save the iterator if there isn't already an element there that conflicts. 3) Perform the erase as usual, and then do mod(), link2(), etc.
Ummm... If I followed your approach I would be incurring two extra copies which is precisely what modify() is meant to avoid. For non-destructive updating you can use update(), that's the idea. If I'm not making myself clear please tell me so.
One thing that I think should be added (though not affecting my vote) is ranked indexes. So just as an index might be unique or non-unique, it can be ranked or not ranked. Ranking gives an index an O(log n) ordinal search. That is, you can search for the ith item according to a certain index in O(log n) time, given an ordered index (obviously, the sequenced indexes would have an O(n) search time). This does change the structure of the nodes, and necessarily makes them bigger for ranked indexes. So it is not a trivial change. However, I am sure that it is doable and would add value to the library.
Yep. The idea of ranked containers came up recently, as introduced by Peter Palotas. I'll add this to the future work section. The most wanted new features seem to be (in this order) serialization, hashed indices and ranked indices.
*** What is your evaluation of the implementation?
[...]
Some of the lines are > 80 columns (e.g.: the copyright notice).
Is this strictly required? If so I'll go thru the code and make the changes. If not, I'd rather leave it like that.
I think that BOOST_NO_MEMBER_TEMPLATES should be deprecated. I don't think there's a single supported compiler in the Boost compiler configs that defines this any more. I think checking against BOOST_MSVC6_MEMBER_TEMPLATES is sufficient, but it would be nice to not even have to check against that.
<off topic> It'd be nice if Boost.Config provided a (possibly automatically generated) reference table showing which compilers do have a specific defect macro.</off topic> Would it be OK to you if we delayed the remotion of this macro till the next dev cycle? I fear I could be inadvertently missing an otherwise supportable compiler.
I do believe the parts that come from other code need to retain the original copyright. The parts that were inspired by, but not directly derived from, another implementation probably don't need a copyright notice, but should probably give a mention in the copyright, at the least as a matter of professional courtesy.
No problem. Apart from stl_set.h I borrowed nothing from other sources. Will add the (c) where appropriate.
*** What is your evaluation of the documentation?
[...]
Here is a somewhat minor nitpick. In the tutorial, the index_list is specified as so:
(type of index)<[(tag)[,(key extractor)[,(comparison predicate)]]]> (type of index)<[(key extractor)[,(comparison predicate)]]>
I would change it to thus:
(unique | non_unique)<[(tag)[,(key extractor)[,(comparison predicate)]]]> (unique | non_unique)<[(key extractor)[,(comparison predicate)]]>
Yes, why not. Consider it changed.
It would be nice to be able to read through the documentation like a manual. Thus, next links on each page would be appropriate.
On the performance page, you state that the tests were performed on a system with 260 KB "RAM memory", running W2K. I'm absolutely certain that is not correct. ;) "256 MB RAM" sounds a lot more likely.
You're absolutely correct. Fixed. Thanks.
Something that I think should be added to the documentation is a concept page that lists the main concepts in IndexedSet and a concept interface a la the SGI STL reference (www.sgi.com/tech/stl).
More on this later down the post.
*** What is your evaluation of the potential usefulness of the library?
[...]
*** Did you try to use the library? With what compiler?
[...]
*** How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
[...]
*** Are you knowledgeable about the problem domain?
[...]
*** Do you think the library should be accepted as a Boost library?
Yes, most definitely.
Great! The score is 9-0 so far.
*** Naming issues:
Here's my take on names, but should not be construed as affecting my vote for inclusion...
Namespace: I think too many namespace levels are not helpful. A separate 'container' namespace seems a bit superfluous to me. There is no danger in name clashes within Boost between container libraries and other kinds of libraries that I can see, and I don't see that it provides a significant documentation benefit. I think additional namespace depth is most appropriate for collections of algorithms, where a proliferation of names is more likely to lead to name collisions.
Well, I stated previously that I'll do what people agree on. I don't know if the final decision should be made by Pavel as the review manager. IMHO, qualified identifiers will be so long anyway that having an additional ::container:: won't hurt much.
Library name: I don't think IndexedSet is so bad, but an alternative that I like is CompositeSet. Then there could be a Composite Sorted Associative Container concept which would support the notion of containers with multiple keys. Then CompositeSet would be a model of Composite Sorted Associative Container. A synonym for Sorted Associative Container could be Simple Sorted Associative Container or Trivial Sorted Associative Container.
The main problem with "Set" slipping into the name of the container is that, for instance, the following indexed_set<int,index_list<sequenced<> > > does not have anything to do with sets (it resembles a std::list of constant ints.) For this reason I like Multicontainer better (or something along this line.) <off topic>Reviewers have showed little or no interest in sequenced indices. Seems weird to me, as they can be used to construct a seemingly useful list-like container with fast lookup.</off topic> As for the Composite Sorted Associative Container concept, we have the same problem. Technically, the requirements imposed to current or future index types by indexed_set are much weaker than being some sort of associative container. I cannot even state global complexity bounds (please check the reference, page "Index reference", section "Complexity signature"). I agree with you a concept section would be highly desirable, but here I definitely need some help. What you request is not trivial.
Indexes: According to the American Heritage Dictionary, Fourth Edition, as channeled by www.dictionary.com, "indexes" is preferred to "indices". Another spelling metric I like to use is Google. According to Google, "indexes" returns 5.8 million hits, while "indices" returns 5.5 million hits. So that's only a 5% difference, but it's statistically significant. ;) I personally think the preferred spelling should be used throughout the documentation, but that's more of a nitpick than a criticism.
My Latin (I speak Spanish) heritage makes me favor "indices" to "indexes" (and "minuscule" to "miniscule", etc.) The Google metric could be biased by the fact that "indexes" is not only the plural of "index" but also the 3rd singular formal of the Present tense of the verb "index". May people allow me to retain "indices"? If only as a small concession to those of use who studied and love the olde Latin language.
Anyway, I prefer "ordered index" to "regular index". As far as index types go, I prefer "ordered_unique" to "set_like", due to consistency. I think Ordered Index should be a concept for this library.
Others do also like ordered_unique etc. I do too.
nth_index_type: I don't like the word "nth", personally. I suggest either of the following naming schemes:
nth_index_type -> ordinal_index index_type -> named_index | tagged_index
nth_index_type -> index_byval | index_bynum index_type -> index_byname | index_bytag
Generalize appropriately to the iterator types.
I recently proposed the following template<int N> struct nth_index; template<typename Tag> struct index; template<int N> struct nth_index_iterator; template<int N> struct nth_index_const_iterator; template<typename Tag> struct index_iterator; template<typename Tag> struct index_const_iterator; which seems to me good enough. Don't you like it? The nth_ prefix has some tradition in C++, why not use it here too?
update(): Actually, I do prefer "replace()" over "update()", because it does more accurately reflect the operation.
Me too.
As far as header organization goes, I would think of it this way: What are the major features and concepts of the library, and how will they be used separately or together? Organize the headers in a way that allows users to include feature sets as modules. If you have to, create dummy headers that just include sets of headers that are logically dependent so that users can activate a certain feature by including that header. Also, consider the cost of each header. It is worth the extra effort to isolate expensive headers than cheap ones. Other than that, I don't have any particular suggestions.
Well, I'm gathering all the feedback from the reviewers wrt to naming and header organization and will try to come up with some consistent proposal today or tomorrow. Thank you again for taking the effort to review the library. I hope you can find it useful in the future. (Here goes a challenge: what about writing a multiply indexed map on top of indexed_set? You're the map expert here at Boost ;) Please check the Future work section for a preliminary discussion on the subject of indexed maps.) Best, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

"Joaquín Mª López Muñoz" <joaquin@tid.es> wrote in message news:406802F9.4990B35C@tid.es...
[...] Ummm... If I followed your approach I would be incurring two extra copies which is precisely what modify() is meant to avoid. For non-destructive updating you can use update(), that's the idea. If I'm not making myself clear please tell me so.
Yeah, I'm not understanding where the extra copies would come from. As far as I can tell, it's possible to reorder the operations in modify() without increasing the cost of execution except by a few instructions. This is my understanding of how modify() works now: mod(element); // changes the element immediately and in-place unlink(element); // takes the node out of the index link2(element); // puts it back in at the correct spot This is what I'm suggesting: i = find(new_element); // look to see if modify() can even succeed if (*i == new_element) return; mod(element); // now change the node, since modify() will succeed unlike(element); // same as before link2(element, i); // reinsert, but use i as a hint (which will be correct) I don't see any copies being made at all (except possibly of an iterator, which should hardly be prohibitively expensive). What is new is that you need to be able to look at the changed value without actually changing anything. That's why I suggested a change to the Modifier function object: class change_name { public: change_name(std::string const& new_name) : name_(new_name) { } std::string const& value(void) const { return name_; } void operator()(employee& em) const { em.name_ = name_; } private: std::string name_; }; So find(element) is something like lower_bound(mod.value()). The complexity shouldn't change because in both cases, you have to perform 2 log n searches through the index to remove and then relink the node. The only difference is when you perform those searches. I'm saying take the second insert search and move it to the beginning of the operation, so that you know if you can succeed before you unlink the node. If I'm missing something, let me know.
[...]
Some of the lines are > 80 columns (e.g.: the copyright notice).
Is this strictly required? If so I'll go thru the code and make the changes. If not, I'd rather leave it like that.
I don't think it's strictly required, but a lot of people complain about long lines.
<off topic> It'd be nice if Boost.Config provided a (possibly automatically generated) reference table showing which compilers do have a specific defect macro.</off topic>
That would be great, but as with many things, complaints are usually satisfied by the complainer. ;)
[...] Great! The score is 9-0 so far.
I think it's the review manager's job to keep track of that, but I guess a little enthusiasm doesn't hurt. ;)
[...] Well, I stated previously that I'll do what people agree on. I don't know if the final decision should be made by Pavel as the review manager. IMHO, qualified identifiers will be so long anyway that having an additional ::container:: won't hurt much.
It won't hurt, but if it won't help, why should it be there? We can add gratuitous namespace levels all day long, but that doesn't mean we should.
[...] The main problem with "Set" slipping into the name of the container is that, for instance, the following
indexed_set<int,index_list<sequenced<> > >
does not have anything to do with sets (it resembles a std::list of constant ints.) For this reason I like Multicontainer better (or something along this line.)
Perhaps, but "multicontainer" sounds *too* generic. I would expect something with that name to support any number of back-ends, like vector, deque, etc. Actually, come to think of it, that might not be such a bad idea. However, it wouldn't really fit the implementation of the library, because the container is a node-based one, and vector wouldn't play as nicely as the others. But if you could not only created computed indices, but also *virtual indices*, then you could create an associative vector! However, this might exceed the scope of the library. By a virtual index, I mean that the vector itself would remain sorted, and you would have an index that performs a binary search without actually storing any additional node information. That sounds like a big mess, though. The reason I think that "Set" is ok is that the STL "Set" is only vaguely related to mathematical sets. The only property of essence that is related to mathematical sets is the uniqueness property, and even that is violated by the multiset. The vagarities of computational performance necessitate that the STL notion of Set be stricter than the mathematical notion for it to be usable. In the same way, I think that IndexedSet need not strictly be even an STL Set for similar reasons. It supports the "essential properties" of uniqueness and intrinsic ordering, and adds additional concepts which cater to computational practicalities. It's not *merely* a container, but a special kind of container. It's not truly a generic container, so I think it would benefit from a more specific name. It's primarily associative, and that's the essence of the STL Set, which is why I think your container ultimately *is* a set, even though a degenerate configuration may not be.
<off topic>Reviewers have showed little or no interest in sequenced indices. Seems weird to me, as they can be used to construct a seemingly useful list-like container with fast lookup.</off topic>
This is probably because people who need the fast lookup usually don't need the original insert order, so the list aspect of it has limited usefulness. However, I can think of a few use cases where it might be handy, so I suspect that really, this is a feature waiting to be discovered.
As for the Composite Sorted Associative Container concept, we have the same problem. Technically, the requirements imposed to current or future index types by indexed_set are much weaker than being some sort of associative container. I cannot even state global complexity bounds (please check the reference, page "Index reference", section "Complexity signature").
Ok, so if the concept is not a refinement of Associative Container, then create a new concept!
I agree with you a concept section would be highly desirable, but here I definitely need some help. What you request is not trivial.
Then let's take a first stab at it. What you have is similar to an Associative Container, but is fundamentally different. The way in which it is different is that there is more than one way to access the data. And, as you say, it is like multiple containers in one. So I think the most fundamental concept here is Composite Container. The reason we don't want to use "Multiple" is that "Multiple Associative Container" means "multiset" and "multimap" (not my favorite terminology, but nobody asked me when they were naming them ;). Let's rip off SGI for a minute: Description A Composite Container is a variable-sized Container that supports retrieval of elements (values) based on one or more keys. It supports insertion and removal of elements, but differs from an Associative Container in that the complexity of the operations depends on the type of key indices used. [insert additional discussion here] Refinement of Forward Container Now, here we have a tricky issue. By default, IndexedSet *is* default constructible, but we can't say that Composite Container should be, because IndexedSet might *not* be default c'tible if one of the key types are not. The STL solved this by simply implicitly requiring key comparators to be default c'tible, but perhaps this requirement is not justified. Anyway, let's continue: Associated types [this part is lengthy, but I think you know what to fill in here] Notation [this part should be obvious as well] Definitions [just rip off SGI some more ;)] Valid expressions [this is where the interesting stuff goes] Expression semantics [this is more of the meat of the concept] Complexity guarantees [just put your conditional complexity analyses here] In particular, I think you should note that both ordered and non- ordered indices are possible, and give separate sets of guarantees for each, noting how the complexity is bounded from below by the slowest index type. I don't see how you can do much better than that, but I think at least that much is required. Invariants [you probably know what to put here, for the most part] Models * indexed_set (of course) * bimap (if anyone makes it ;) That's a start anyway, and if you fill in as much of that as you can, I think others will be able to help you fill in the rest. It also might help if you define other concepts first, like Ordered Unique Index, etc. I know it's a lot of work, but I think it's worthwhile (especially for people wanting to extend the library, i.e.: by defining custom index types).
[...] My Latin (I speak Spanish) heritage makes me favor "indices" to "indexes" (and "minuscule" to "miniscule", etc.) The Google metric could be biased by the fact that "indexes" is not only the plural of "index" but also the 3rd singular formal of the Present tense of the verb "index".
Good call! That was some sloppy reasoning on my part. ;)
[...] The nth_ prefix has some tradition in C++, why not use it here too?
I guess there is "nth_element()". I've never had need for it, so I didn't even notice it. Dave --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.581 / Virus Database: 368 - Release Date: 2/9/2004

David B. Held wrote:
Indexes: According to the American Heritage Dictionary, Fourth Edition, as channeled by www.dictionary.com, "indexes" is preferred to "indices".
My dictionary mentions both, but I have never heard an educated person in my life use the word "indexes" as a plural for index rather than the word "indices". And I don't particularly care what the Google hit rates are since a great many people are poorly educated.

very funny indeed. http://www.djindexes.com/jsp/index.jsp Quoting Edward Diener <eddielee@tropicsoft.com>:
David B. Held wrote:
Indexes: According to the American Heritage Dictionary, Fourth Edition, as channeled by www.dictionary.com, "indexes" is preferred to "indices".
My dictionary mentions both, but I have never heard an educated person in my life use the word "indexes" as a plural for index rather than the word "indices". And I don't particularly care what the Google hit rates are since a great many people are poorly educated.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Edward Diener" <eddielee@tropicsoft.com> wrote in message news:c4alki$cnj$1@sea.gmane.org...
David B. Held wrote:
Indexes: According to the American Heritage Dictionary, Fourth Edition, as channeled by www.dictionary.com, "indexes" is preferred to "indices".
My dictionary mentions both,
In the same order as the AHD, I presume?
but I have never heard an educated person in my life use the word "indexes" as a plural for index rather than the word "indices".
Maybe all the educated people you know speak Latin. ;) My experience is just the opposite. Usually, when I hear someone say "indices", they come across as a bit pretentious.
And I don't particularly care what the Google hit rates are since a great many people are poorly educated.
You sound like a dyed-in-the-wool prescriptive grammarian. ;> For us descriptivists, grammar is a democracy, so majority rules. Dave --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.581 / Virus Database: 368 - Release Date: 2/9/2004

In article <c4alki$cnj$1@sea.gmane.org>, "Edward Diener" <eddielee@tropicsoft.com> wrote:
My dictionary mentions both, but I have never heard an educated person in my life use the word "indexes" as a plural for index rather than the word "indices". And I don't particularly care what the Google hit rates are since a great many people are poorly educated.
I always thought that indexes are in a book and indices are in a sequence. m-w.com agrees with that (as well as mentioning additional meanings of the word). meeroh -- If this message helped you, consider buying an item from my wish list: <http://web.meeroh.org/wishlist>
participants (5)
-
David B. Held
-
Edward Diener
-
Joaquín Mª López Muñoz
-
Miro Jurisic
-
on2005@columbia.edu