Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2002-12-13 23:06:34


"Tanton Gibbs" <thgibbs_at_[hidden]> escribió en el mensaje
news:002601c2a300$a338c790$aed8550a_at_Corp.Acxiom.net...
> > Thanks to the clear arguments made by the reviewers, I see the picture a
> lot
> > more clear now.
> > Specially the fact that optional<> is itself a container, or perhaps, a
> > union of T and nil_t.
> > But your previous post were you developed those concepts were very
helpful
> > as an argument to keep the pointer-like interface.
>
> I hope you mean "instead of the container interface."
>
If you are refering to "empty()", "ref()" and relops; yes,that's what I
meant.

> I don't have a problem with the pointer-like interface, it makes sense to
> me...I prefer the value
> based one, but I understand that is just personal preference. However, I
> definately don't
> think we need to mix the two as that would just be confusing.
>
I think it can be done in a way as to not make it confusing.
For instance, iterators also have operator*() and ->(), yet they are not
pointers.
Certainly, they are _a lot_ more like pointers than optional<> because they
have pointer semantics in terms of shallow-copy and aliasing, but,
for instance, you cannot delete an iterator, but I don't think that
the pointer-analogy had drawn peoplo into that sort of mistakes.
For optional<>, the key to sucess resides in the way you present it,
and in the way the pointer-like interface is used.

>
> For what its worth, I prefer the union concept. Union semantics clearly
> state that
> you can have either or (i.e., not both).
Yes.
But I think that a container is even better, because containers inherently
models the fact that you can have a value or not.
This is closer in meaning to optional than a union.
It is an error to try to access one element of an empty container
just as it is an error to try to access a non-existent value.
For a union to behave like this, the signal type has to be carefully
designed, as a signalig NAN for instance.
The union mapping is good, but the container mapping is better becuase
the undefined behaviour of invalid access is directly supported by the
container concept, while the union concept requires the additional
element of a type with semantics unfamiliar to C++.

> Furthermore, the fact that Joel
> identified
> optional<> as a specialization of variant<> reinforces my belief that a
> union based
> concept would be easier to explain.
Yet Peter identified optional<> as a container of 0 or 1 elements.

> When you start explaining this in terms
> of pointers
> people immediately start assuming memory management and aliasing;
>
Exactly! My mistake was to start explining it in terms of pointers. :-)

The extended documentation I'm working on takes the oposite route: Develops
the concept of optional as a container of fixed capacity-1 which can have
at most one element. It then explains the semantics of such a container
and proposes the container-like interface.
Then it goes about explaining how pointers are used to _refer_
 (only to refer) to opitional objects, formalzing the concept of
""OptionalPointee"; and shows why pointer _semantics_ are _not_ appropriate
for an optional wrapper.
Next, it concludes that modifing _part_ of the container-like interface with
_part_ of pointers-interface makes the possible undefined value access
operations familiarly looking, which is convenient and self-evident;
and even allows _some_ uses of optional<> to be placed on generic code.
Finally, it summarizes with the explanation that the pointer-like interface
is not to be taken to mean that optional is a pointer.

> however,
> optional<>
> is not about those. optional<> in my opinion is clearly a union of T and
> nil_t.
I find the container model more fit because nil_t alone does not show
the error which is implied by it apearance as the result of value access.

> Furthermore,
> the fact that people have, in the past, used pointers for optional values
> does not necesarrily mean
> that is the right vision to propogate.
True.

> Pointers were the easiest way of
> providing an optional value;
Yes.

> it's not that they were comprehensible, or even that they made a great
> mental model, just that they were
> convienient.
I disagree here.
With an optional value, access to its value has undefined behaviour, or at
least it should.
With a union-like interface, this is not so because the union has always
a well defined state, so if you try to accesss an uninitialized optional,
this model gives you nil_t.
nil_t by itself is not undefined, so to make sense of the concept of
optional value, which itself implies that the value might not exist,
either the programmer or the interface-under-the-hood must make sure
that the result nil_t is treated as a postcondition violation.
If you trust my experience with this tool, I assure you that if you are
accesing the value of a conceptually non-existent object,
 you've made a mistake on the code because the execution path
should never had reached that point.
This is why I prefer the container model: You cannot extract one
element of an empty container. If you try, you get undefined behaviour.
However, the syntax of a container interface does not help you
to make sure you have checked for non-emptyness. Of course,
this happens all the time with any container and it has alawys
been the programmers responsability to make sure of the object
you try to access is actually there.

But the syntax that is used with pointers to convey optionality
is _much_ better because the fact that the value you are trying
to access may not exist is clearly spoted by the dereference -with
its familiar and well known implications-.

Whenever you see: (*opt) or (opt->) you know, beyond any doubt,
that 'opt' must better refer to an existing object:
optionality is self-evident with a pointer-like access syntax.

> You have a chance now to redesign our notion of what
> constitutes an optional value--to
> make it comprehensible and convienient.
Indeed.
I'm contourting my mind to do this as better as I can.

> Holding on to history for history's
> sake is not always the best
> option.
>
True... holding on to it for history's sake alone treats evolution;
but learnig from history is quite different;
some things are repeated time after time simply because
they really work.

Fernando Cacciola


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk