|
Boost : |
Subject: Re: [boost] [Review] ITL review starts today, February 18th
From: Joachim Faulhaber (afojgo_at_[hidden])
Date: 2010-02-26 20:50:29
Hi Barend!
I am delighted to hear that you are enthusiastic about my library :)
2010/2/26 Barend Gehrels <barend_at_[hidden]>
> Hi Joachim,
>
> This is not yet the review.
>
> I'm about halfway and I'm enthousiastic. I've done two small projects
> inspired on my needs and all I tried is working good, it definitely is a
> useful library.
>
>
> Questions /remarks though.
>
> 1) The set union is modelled as += (doc: "So interval_sets define an
> operator += that is naturally implemented as set union and an operator -=
> that is consequently implemented as set difference"), set intersection as &=
> (according to the doc definition and man_power sample).
>
> However, a union is more or less like an OR operation, an intersection like
> and AND operation, so I would have expected that union would be |=.
> According to the manual, in another place, that is also supported.
>
> Yes, it is. I assigned the identical union semantics both to += and |=
although reluctantly because I think operators are "precious"...
> Boost.Polygon(BP)/GTL also supports both, for union. Is it intentional that
> two operators are implemented for the same operation in these two libraries?
> And if so, why is that not done for the intersection (having synonym *= in
> BP).
>
> ... because operators are "precious".
(1) They are not (yet) producible in c++. We have to get by on a small set
of them. So its unwise to waste them.
(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.
(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}
(4) With *= and &= this is different. * is in my view not an "archetype" for
intersection.
(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 *= .
> Boost.dynamic_bitset also implement all of these:
> dynamic_bitset& operator&=(const dynamic_bitset& b); Bitwise-AND ...
> dynamic_bitset& operator|=(const dynamic_bitset& b); Bitwise-OR's...
> dynamic_bitset& operator^=(const dynamic_bitset& b); Bitwise-XOR's...
> dynamic_bitset& operator-=(const dynamic_bitset& b); Computes the set
> difference of this bitset...
>
> Boost.Geometry does not (yet) implement operators so we look in a way to
> conform, if possible, and would like to avoid to introduce synonyms. So I
> would advocate, for (at least) the four libraries Boost.dynamic_bitset,
> Boost.Polygon, Boost.Geometry and ITL, the usage of operators conform
> dynamic bitset, so the following:
> &= for intersection
> |= for union
> ^= for symmetric difference (as is done in both ITL and BP)
> -= for difference (as is done in both ITL and BP)
>
> 2) Same scope, the "boolean" functions "is_disjoint", "contained_in", we in
> Boost.Geometry have named them (according to ISO/OGC) as "disjoint" and
> "within". The following functions match: "intersects", "contains" and
> "touches". And, besides that, ISO/OGC also describe "equals", "overlaps"
> (where overlaps is roughly intersects, but not completely within, and not
> touches).
>
> So actually we're nearly there, there are just some small differences in
> names/synonyms.
>
> Not being a geometry developer I'm not very aware of the ISO/OGC standard.
So I mainly oriented my decisions on greps of boost/ , maths, sometimes
google source search, my own preferences and the principle of least
astonishment. Because the functions you mentioned are functions on sets,
which are so fundamental, the naming should IMO be uniform across all of
boost. An existing standard is a strong orientation, but even standards
sometimes contain namings that can be unfortunate.
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 is_disjoint would be my favorite but I could live with disjoint too.
is_disjoint / disjoint could be completely abandoned in my view, because it
has a negated meaning [disjoint == !intersects] the positive naming is
always more intuitive. I made a google code search. intersects greatly
outnumbers disjoint / is_disjoint.
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.
Cheers,
Joachim
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk