
Hi Joachim,
(2) operators are like semantical archetypes. Pretty early in school we
make contact with =, <, +, - . They carry semantical invariants not only for mathematicians but for almost every educated human being. This is like a treasure that can be harnessed for those parts of generic libraries that we want to be maximally intuitive to use.
I understand but only if it is really intuitive for everyone. I've seen that you refer to segmentational fineness, coupled to operator>, which is for me not so intuitive ("x > y // means that x is_finer_than y"). I would state that a function with a describing term is often more easy to use and to interpret.
The example is a little specific. The operator > is induced by the fact
2010/2/27 Barend Gehrels <barend@geodan.nl> that segmentational_fineness<T>::value yields an integer constant, which is larger if the type T is finer. Looking at the stl I think operator < is a good example for a very pervasive operator with a consistent interpretation across a lot of class and function templates. It is also generally expected as default for compare functor types. I would say that operator < in the stl is the classical example for a consistent and pervasive usage of an operator. (3) While with += and |= I feel kind of coerced to assign the same
semantics: + is the primary operator of combining object of some type, which is union (for sets) | is equivalently intuitive from the boolean view of set union a | b = { x : x in a || x in b}
I doubt that += is so intuitive in this case. Combined with a scalar, an
interval [2,5) += 3 might intuitively go to [5,8), e.g. delayed by 3 minutes.. I like the symmetry of || and && for or/and and |= and &= for union and intersection, which are the or and and in set theory. Therefore, I would reserve the += for something else, because they are sparse, as you stated ;-). Or just don't use it.
... hmm ... I have thought about that as well. [2,5) += 3 starts to introduce interval arithmetics. Although this could be pretty handy I decided to leave interval arithmetics out. The reason is, that the domain_type of intervals and interval containers does not need to be a number. It only requires a strict weak ordering. So arithmetic operations would work for a subset of all possible domain_types only.
For numeric domain_types it is obviously interesting to be able to perform arithmetic operations and to reserve += for that. To keep things simple I ruled that out for the time being. But yes, this is an argument to think about *saving* operator += . But there are more problems. If we defined += for arithmetic addition (e.g. on interval_sets), we would want to use -= for subtraction, which is already occupied for set difference :(
On the other hand, the difference is -=, so subtracting a set, and a union is +=, so adding a set, yes it is intuitive and symmetric... We need the operators U and U/upsidedown here to make it mathematical... ;-)
(4) With *= and &= this is different. * is in my view not an "archetype"
for intersection.
I do agree with that. Besides that, the *= might stand for the Cartesian product as well.
Right, also a good candidate.
(5) Yet, the most important reason is that I'd like to save * for scaling:
2 * {1,2} = {2,4} because this *is* IMO an archetypal meaning for * (6) In the more freaky parts of my semancial studies on interval_maps I found that specific instantiations e.g.: interval_map<int,double,total_absorber> are models of a concept 'indefinite vector' of a vector space, if a scalar multiplication was added. To be able to add this basic operation later I wanted to save * and *= .
Yes, 2* is inuitively convenient for scaling, but is scaling of intervals an often occuring need?.
Yes, we had use cases, where we had intervals from of different time granularity. So we had to scale them to a common time scale. For the boost submission I took that function out of the ITL. But it has its applications.
In the 2/3 D case we have transformations which scale,translate and rotate, here you probably have scale and translate, and I think I would not attach an operator on it, or make it consequent with translation...
There is another function as well, not being discussed yet, what we in GIS call the "buffer". So {1,2} buffered by 0.1 would be {0.9,2.1}. Is that supported by ITL and do you think it needs an operator, and which? It is different than scaling because an interval set {1,2},{3,4} would be {0.9,2.1},{2.9,4.1}. For intervals useful if you need 5 minutes extra in all schedules on both sides.
Seems not terribly essential to me but may be useful to add.
I am always struggling with this: is_whatever(x) : This is my preference for boolean functions (except natural cases like intersects, contains), because whatever(x) is often a good choice for a non boolean function. On the other hand the whatever(x) version is stl-style and also of course generally shorter.
So why actually is "contains" a natural case and "disjoint" is not?
(1) My glass contains beer.
(2) Your glass disjoint from mine. =)
Do you find it a good idea to have / create a common picture of operators
and functions and if yes, is it still possible to adapt?
The more fundamental concepts are, and sets / maps are *very* fundamental,
the more important is the quest for a really good, intuitive and systematic naming. I am in favor of that and I am willing to adapt.
OK. So we have fundamental concepts for at least operators, and for boolean
operators which overlap these libraries...
In a way all of boost is kind of an effort to converge on common designs, concepts and notations. I like that =)
Best, Joachim