Boost logo

Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2004-02-18 15:04:11

Hi, the library is so big that I will post the review in chunks.

Referencial Integrity and Side Effects:

I never really bought the pure FP argument about no side effects.
I'm unconvinced that all programming tasks can be _elegantly_ solved without
side effects.
In particular, one common task that always seems to bend this intended
principle is Outputing.
For example, FC++ itself claims to adhere to that principle by promoting
that functoids take only non-mutable arguments, but then it finds itself
beding that claim when it comes to output: the insertion functoid takes a
_mutable_ argument (it has a side effect).
IMO, this exception is actually indicating that no-side-effects cannot, and
should not be taken to the extreme, because real-life programming cannot get
away without mutable states (or takes a mindset so radically different that
a "C++" programmer can't leave without it)

What I'm trying to say is that I don't like the current design were
functoids are prescribed to take only reference to const parameters, for a
variety of reasons:

1) As I expressed above I don't think that the restrictive paradigm is
actually useful. I like the _guideline_, but I dislike to clutter the design
in order to prevent me from doing what I know is actually right.
I myself tend to be overprotective, but with Boost.Optional I came to learn
to "Trust the Programmer"

2) It turns out that being C++ an "impure" language (from the FP POV),
there's actually no way for FC++ to really disable mutable arguments (I can
always pass a pointer), so the restriction is there only to communicate a
principle rather than to enforce it. However, that fact that FC++ cannot
really avoid mutable arguments will in practice result on a mechanical code
pattern were each mutable argument will be passed as a pointer (as in the
old C days) instead of a reference; but mutable arguments will still exist.
Ultimately, badly designed functoids won't really be prevented at all -which
is the actual intention of the restricted design-, yet well designed
functoids (such as FC++ insertion) will have to pay for an unnatural syntax.

3) FC++ is for C++ programmers, not Haskell programmers. Most of us know how
to follow code patterns to avoid the common pitfalls. There was a time were
many C++ programs were caught by implicit conversions, aliasing subtelties,
life time and memory managment problems, etc... yet we learnt how to deal
with that by means of idioms. With FC++, we will eventually discover the
idioms that will help us avoid referencial integrity mistakes, so I don't
think the library itself should bend the design too much in order to
guarantee that.

4) Referencial integrity is anyway tricky enough to break even into a
library specially designed to protect it.
For example, FC++ uses reference to const objects in order to avoid mutable
arguments, all in the name of referencial integrity. However, a "const&"
parameter is not totally inmune to such problems the way a _true_ by-value
parameter is, because it is after all still a reference, and references
Consider the following aparently contrived example:

inline point transform ( point const& p )
  return point(2.0* p.x * p.y, 0.5 * p.x * p.y);
void foo()
  point p (..whatever...);
  p = transform(p);

On many C++ implementations, the code above will yield an incorrect result
because the return object will actually be constructed in place, producing
an actual code equivalent to:

p.x = 2.0 * p.x * p.y ;
p.y = 0.5 * p.x * p.y ;

and you can see how the aliasing resulted in the _argument_ "p.x" being
modified inside the function.

That example is not too uncommon because any non-linear transformation that
use a linear combination of the coordinates can fail because of the aliasing
if a const& parameter is used instead of a true by-value argument.

... to be continued...

Fernando Cacciola

Boost list run by bdawes at, gregod at, cpdaniel at, john at