|
Boost : |
From: Kevin Lynch (krlynch_at_[hidden])
Date: 2001-10-24 16:43:54
Ed Brey wrote:
>
> From: "Peter Dimov" <pdimov_at_[hidden]>
>
> > namespace math
> > {
> > float const pi_f = ...;
> > double const pi = ...;
> > long double const pi_l = ...;
> > }
>
>
Well, I hate to be difficult, but I'm going to be anyway. While I
understand the arguments people have made, I don't agree with any of
them :-) Templates solve precisely this "multiple names for the same
concept but with different types" problem. I, personally, would not use
the library in this form, as I find this to be an inelegant and fairly
dangerous hack for a number of reasons:
It makes code maintenance a nightmare, since code becomes brittle under
type changes, or even under typos! How many times have you mistakenly
written "doubel"? The compiler can catch that problem, but it is not an
error to write pi_f when you mean pi_l, and I don't believe a compiler
is required to tell you about the mistake (of course, I might be
mistaken about that, and the implementation I use does warn you that you
are making a mistake). The suffixes are ugly warts carrying type
information, and I don't see that it really improves ease of use all
that much. The language has mechanisms to eliminate these problems, and
the compiler is there to enforce correct use of those mechanisms to make
coding easier and more expressive. I haven't heard reasons that are
compelling enough for me to want to throw the safety net out the window
in my own code.
It makes it much more difficult to write generic code that use the
constants; trivial example, but I hope it makes the point:
template<T> complex<T> calculate(complex<T> x){
return pi*x; <<<<<< I can't write this line anymore
}
I would prefer to write something like:
template<T> complex<T> calculate(complex<T> x){
return pi<T>()*x;
}
and be saved from the grief of the hours of debugging that the first
example might cause because the "wrong" pi was used, or worse, the
humiliation of publishing an incorrect result because the code I wrote
silently generated the wrong result. Cross checking and rechecking
results for consistency and sanity is the most time consuming part (for
me!) of writing code for research work, and eliminating or minimizing
type mismatch issues through templates would be an improvement as far as
I am concerned.
I'll note that this non-genericity issue is a substantial impediment to
the speed with which math intensive code can be developed, and
non-generic C++ mathematical code holds no real benefits when compared
to modern Fortran in this regard; C++ only comes into its own in
mathematical applications when you can take into account the more
generic approach that C++ makes possible. But that approach is only
possible when the design of the libraries doesn't prevent you from
exploring those generic options.
> > Note: no 'constants' subnamespace. I know that 'pi' is a constant, thanks.
> > :-)
> > Given these thoughts, I agree that the "constants" namespace can go.
Even for a non-generic constants implementation, I have to disagree.
People have been talking about having of order 100 purely mathematical
constants eventually (yes, there really are that many "essential" and
"basic" math constants), not to mention physical constants; I know that
"pi" is a constant, but what about "gamma" or "Euler5"? Furthermore,
putting short names (like pi and e) and common names (like euler and
gauss) too shallowly in the namespace hierarchy is going to gobble up
common names and end up causing collisions that people are going to
regret later (granted, this isn't as much of a problem currenty in the
boost::math library implementations, but it will severely restrict names
available for future functionality; I'd hate to end up getting stuck
math::euler and math::euler_function or somesuch when a reasonable
alternative exists.); the unreasonable alternative is very long names
that are unpalatable from a usability perspective: EulerNumber5,
TschebyschevConstant2, GammaFunctionOfOneHalf, etc. I'd much rather see
constant::Euler5<Real> (ok, granted, this is long too, but I've left out
the namespace qualifiers above). Some people have already argued in
this thread for not doing things we'll regret later when we can't change
them, and I think this is definitely one of the things that users will
regret later.
> It is still desirable to have a generic interface, but it is allowed to be completely
> different.
Providing two separate interfaces, one a templated interface and one a
non-templated interface is fine, provided: 1) Users of the templated
interface wouldn't be burdened with the non-template interface, and 2)
vice-versa, and 3) neither interface is saddled with a more "onerous"
naming scheme (eg. one lives in boost::math, the other in
boost::math::templated_constants). In other words, I don't want to have
to learn both in order to use one of them, and we shouldn't consider one
of them a "second class citizen". If we end up with both, they should
both be supported with equal vigor by boost. But, having two equal-rank
interfaces for the same set of information screams "multiple namespaces"
to me; I'd hate to see six or more representations of "pi" sitting in
the same namespace (pi_f, pi, pi_l, pi<float>(), pi<double>(), pi<long
double>(), pi<complex<float> >() etc..... ). I think that this is an
excellent example of where a subnamespace DOES make a huge amount of
sense.
> I expect that the strong sentiment for a parentheses-free solution doesn't exist in the
> domain of generic coding.
And I don't have a problem with that; if you want to obtain the benefits
of the generic approach, you're going to have to pay for them somewhere
along the line, and those extra parens are the place. I don't see that
two characters will turn off those that want the benefits; I'm certainly
willing to pay the price.
(I'd also venture to guess that if you are unwilling to type (), you'd
be unwilling to seek out and use a library of constants in the first
place, and boost is almost certainly not the place you would think to go
looking even if you WERE willing; you're far more likely to stick with
the cut-and-paste method or the copy-it-from-a-reference method... but
that is an argument I'm just not willing to defend because I really
can't :-).
-------------------------------------------------------------------------------
Kevin Lynch voice: (617) 353-6065
Physics Department Fax: (617) 353-6062
Boston University office: PRB-565
590 Commonwealth Ave. e-mail: krlynch_at_[hidden]
Boston, MA 02215 USA http://physics.bu.edu/~krlynch
-------------------------------------------------------------------------------
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk