. I'm reviewing Apple's Cocoa Objective-C,
and noticing again a mutable type is
seen as a subclass of a constant?
it would seem more intuitive if
constancy was an orthogonal attribute:
any type can optionally be described as
constrained to a constant state .
. it also seems more intuitive to
not partition the available commands
the way subclassing does;
eg, I might want a search function that is
combined with a search&replace operation
( if the target object is modifiable,
my search also does replaces ).
. if mutable is a subtype of constant,
then we need 2 assignment operators
(one is just for initializations,
while the other is just for the mutable subtype);
whereas, if constancy is expressed as a
constraint on a base type
rather than as a supertype for a subclass,
then we can reuse the assignment operator
as the initializer; and, in order to
enforce the constancy constraint,
we prevent the object from being subject to
out-mode or inout-mode parameters
after the initial assignment is made .
[12.10: ie, we enforce the fact that
an out.mode-pointer to constant T
is not a subtype of out.mode-pointer to T;
even though a value of constant T
is a subtype of value of T .]
. in order to help the compiler with
enforcing the constancy constraint,
every operation should ask for
only the parameter permissions it requires,
therefore search and replace
would need to be separate commands
because the operation, search(x, target),
needs only in-mode parameters,
whereas this operation writing to x:
needs an inout parameter .
. there are 2 reasons for constants:
# the primary purpose is an assurance that
the obj's state doesn't change;
because, the more we can
be sure that things are constant,
the more reduced the system's complexity is;
# space efficiency:
. constants give us the ability to
share via input-only pointer
instead of having to copy .
. instead of a [is this a constant obj].tag
taking up a bit on every obj,
we could use a [pointer to const] system datatype .
. the pointer won't be the expected type,
but every type mgt can read the supertype.tag,
and see that it's a pointer to constant,
and know that the object being referenced
is what they want to pick up,
and that it should be treated as a constant .
. this couldn't work because of efficiency:
if we were to optionally have pointers
then every parameter of every operation
would need a supertype.tag
in addition to the subtype.tag:
. the supertype.tag would be indicating
whether this was the expected type
or a pointer to the expected type .
. only the any.type should need a supertype.tag .