comp.lang.ada
 help / color / mirror / Atom feed
* Re: Syntax for tagged record types
@ 1997-05-24  0:00 Robert Dewar
  1997-05-25  0:00 ` Matthew Heaney
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Robert Dewar @ 1997-05-24  0:00 UTC (permalink / raw)



Matthew says

<<I think that using discriminants as "constructor arguments" is a real
kludge, and obfuscates declarations.  Ada 95 doesn't have constructors, so
let's not try to fight the language.>>

Most people find the use of discriminants as "constructor arguments" a
natural and powerful feature in Ada (though naturally they don't think
in terms of this terminology).

You can declare that "I think X is a kludge" for any X, but such a statement
is only helpful to discussion if you give some idea *why* you think this.







^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Syntax for tagged record types
  1997-05-24  0:00 Syntax for tagged record types Robert Dewar
@ 1997-05-25  0:00 ` Matthew Heaney
  1997-05-26  0:00   ` Robert A Duff
  1997-05-27  0:00   ` Jon S Anthony
  1997-05-27  0:00 ` Tucker Taft
  1997-05-27  0:00 ` Dale Stanbrough
  2 siblings, 2 replies; 6+ messages in thread
From: Matthew Heaney @ 1997-05-25  0:00 UTC (permalink / raw)



In article <dewar.864485829@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:

><<I think that using discriminants as "constructor arguments" is a real
>kludge, and obfuscates declarations.  Ada 95 doesn't have constructors, so
>let's not try to fight the language.>>
>
>Most people find the use of discriminants as "constructor arguments" a
>natural and powerful feature in Ada (though naturally they don't think
>in terms of this terminology).
>
>You can declare that "I think X is a kludge" for any X, but such a statement
>is only helpful to discussion if you give some idea *why* you think this.

I say this because "discriminant" should mean "tag in a disjoint union." 
Records are Cartesian product, and discriminated records are disjoint
union.  And that's all discriminate record should mean.

But "tag of a disjoint union" is a far different thing than "arguments to a
constructor."  And when you use discriminants for the latter, the
declaration is ambiguous, and I the maintanence programmer have to do work
to figure out what you mean.

It's not unlike another sin commited by many Ada programmers.  That's when
you use "and then" in predicates, when you really mean "and."  Many Ada
programmers do this in a naive attempt at some sort of optimization, but it
should only be used when you want to enforce an order dependence on
evaluation of the parts of the predicate.

Now when I see a predicate with "and then," it's ambiguous, because I don't
know whether you're making (an unnecessary) optimization, or whether there
really is an order dependence.  You, the writer of that code, are being
unthoughtful to me, the maintainer of that code, because you have abrogated
your responsibility to tell me what you mean explicitly and unambiguously,
and therefore I am put in the unwanted position of having to guess.

That Ada evaluates all the parts of a predicate, even if one early part
evaluates to false (say, in a complex Boolean expression with more than one
"and"), is an _essential_ characteristic of the language.  When a
programmer uses "and then" everywhere, he is really wishing that the
language were some other way, and is desperately trying to somehow "fix"
the language.

But this is no fix at all.  And I the poor maintanence programmer am the
victim of your thoughtlessness.

The language is the way it is.  Accept that.  If it doesn't do exactly what
you want, stay within the spirit of the language anyway, and justify it by
realizing that Ada gives you a lot a things you wouldn't have if you were
programming in another language, so you're still operating in the red.

Respecting the spirit of the language means not using a discriminant as a
constructor parameter.  Norm stated in his book that "In Ada, the role of
these [constructor] parameters can be played by discriminants." (p. 579) 
Now, I like Norm, and I thank him a thousand times over every time I can
pick up his book and answer a question, but this is horrible advice.  When
you use a discriminant as a constructor parameter, the purpose of the
discriminant is now ambiguous.  And I the poor maintanence programmer have
to figure out what you mean.  So I have to guess, and I might guess wrong.

Respecting the spirit of the language means not using short-circuit control
forms as an optimization.  When you do that, the short-circuit form is
ambiguous, and I have to figure out whether you meant "this is an
optimization" or "this is an order-of-evaluation dependency."  I have to
guess what you mean, and I might guess wrong.

It's not unlike Ada 83 programmers who, in their zeal to "repair" Ada,
"simulated" inheritance hierarchies.  I can tell you this causes nothing
but obfuscation of the code, and any supposed benefits of "reusability" or
"being more object-oriented" were more than offset by the attendent
complexity of trying to use a solution not directly supported in the
language.

The whole point of software engineering is to _minimize_ complexity.  You
must be _unrelenting_ in seeking out techniques to _simplify_ the software. 
So when you make your code more complex by "simulating" inheritance, in
some sort of quixotic attempt to be "more object-oriented" - because you've
been led to believe that "more" object-oriented is "better" - then I have
to ask myself what kind of engineering this is.

Ada 83 is not object-oriented.  Accept this.  Use the tools provided by the
language _as_is_.  Because when you try to bend the language to "repair"
it, you distort the clarity of your solution too, because it's expressed in
a way that isn't natural for the language.  And when your solution isn't
crystal clear, then I the maintenance programmer have to figure out what
you mean.  I don't want to figure out what you mean; I want you to tell me,
unambiguously.

This doesn't mean being object-oriented isn't good.  It's just that Ada 83
doesn't have inheritance (technically, "type extension") or polymorphism. 
So respect that "limitation."  Rationalize this by saying to yourself that
the language has many other good features that aren't in other languages,
so you're still ahead in the game.

One nascent (maybe not-so-nascent) phenonmenon that I've observed is a
dissatisfaction with the fact that, in Ada, a module is not a type, "you
know, like in other languages."  I've seen programmers name their abstract
data type "object" or "instance," so that the "real" name is only obtained
by qualifying the type name with the package name, as in

   The_Stack : Stack.Object;

This is a horrible naming convention.  It represents a desperate attempt to
repair the language, by trying to force the package to be a type.

What are you going to name the iterator for the stack?  "Object" has
already been used within that namespace.  What you'll probably do is create
a child package, so you can again name your iterator type
Stack.Iterator.Object.  This too is a mistake: the point is that the
language was _designed_ so that you can declare closely related abstract
data types _together_ in the _same_ package.

This proliferation of packages - as many packages as there are ADTs - is a
complete mistake, and is orthogonal to the intended usage of the language. 
The whole point is to prevent getting lost in a sea of types (as you do in
other languages, where the module is a type), by using packages as a
higher-level organizing principle.  If you have as many packages as types,
then what have you gained by having packages at all?

In Ada, a package is a module.  It is not a type.  It is a language tool to
give the programmer explicit control of namespace - nothing more, and
nothing less.  Accept this, and respect the language, by giving the type
itself the name of the abstraction.  Respect the intended usage of Ada by
putting the data structure ADT and its active iterator ADT togther in the
same package.

Yes, I know this isn't how it is in other languages, but rationalize it by
saying that there are plenty of things you do have in Ada that you don't
have in other languages.  And plently things you don't have to do. 
(Example: In Ada, you don't need a "friend" construct, because visibility
is implied by the colocation of types in the same package.)

It's not unlike the German language.  Those silly Germans, they put all the
verbs at the end of the sentance.  So let's all try to "fix" German, but
putting all the verbs where they "should" be.

Obviously, this would be horrible thing to do.  That verbs go at the end of
the sentance is an _essential_ characteristic of the German language. 
Somehow, the Germans manage to speak with each other just fine, thank you
very much.  Imagine that!

You must think in the paradigm of the computer language to effect the most
elegant solution to a problem.  It does no one any good (least of all the
poor maintenance programmer) when you fight Ada by trying to incorporate
"better" features (say, automatic short-circuiting) found in other
languages, without those features being directly supported.

Here's a quote from Jean Ichbiah, on the nature of design: "One can only
reach a harmonious integration of several features by immersing oneself
into the logic of the existing parts."

It means that the language is the way it is, and you must immerse yourself
in the language, warts and all, to achieve beauty and harmony.  So when I
say using discriminants as a constructor is a "kludge," I'm saying that
you're fighting the language.  Ada 95 doesn't have constructors.  That is
(for now) an essential characteristic of the language.  Use discriminants
as discriminants (that is, as the tag in a disjoint union), and accept that
you don't have constructors, and rationalize this by realizing that the
language is pretty good even without them.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Syntax for tagged record types
  1997-05-25  0:00 ` Matthew Heaney
@ 1997-05-26  0:00   ` Robert A Duff
  1997-05-27  0:00   ` Jon S Anthony
  1 sibling, 0 replies; 6+ messages in thread
From: Robert A Duff @ 1997-05-26  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002505971422590001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>I say this because "discriminant" should mean "tag in a disjoint union." 
>Records are Cartesian product, and discriminated records are disjoint
>union.  And that's all discriminate record should mean.

It wasn't that way in Ada 83:

    type T(Discrim_1: Natural; Discrim_2: Character; Discrim_3: Boolean) is
        record
            Comp: String(1..Discrim_1) := (others => Discrim_2);
        end record;

I'm not sure whether you consider Discrim_1 as being a "tag in a
disjoint union," but Discrim_2 certainly isn't -- it's being used to
create an initial value.  Discrim_3 isn't either -- it isn't used inside
the record at all, and is merely a constant component of the record,
initialized at the point of each object declaration.

It seems to me that using discriminants inside an Initialize procedure
is a reasonable generalization of the Ada 83 concept illustrated by
Discrim_2.

>It's not unlike another sin commited by many Ada programmers.  That's when
>you use "and then" in predicates, when you really mean "and."  Many Ada
>programmers do this in a naive attempt at some sort of optimization, but it
>should only be used when you want to enforce an order dependence on
>evaluation of the parts of the predicate.

I agree with you about "and then".  But I don't buy the analogy with
discriminants.

- Bob




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Syntax for tagged record types
  1997-05-24  0:00 Syntax for tagged record types Robert Dewar
  1997-05-25  0:00 ` Matthew Heaney
  1997-05-27  0:00 ` Tucker Taft
@ 1997-05-27  0:00 ` Dale Stanbrough
  2 siblings, 0 replies; 6+ messages in thread
From: Dale Stanbrough @ 1997-05-27  0:00 UTC (permalink / raw)



Robert Dewar writes:

"Most people find the use of discriminants as "constructor arguments" a
 natural and powerful feature in Ada (though naturally they don't think
 in terms of this terminology).
 
 You can declare that "I think X is a kludge" for any X, but such a statement
 is only helpful to discussion if you give some idea *why* you think this."


We had this argument a few years back now, and I think it was David Emery 
who posted about opening a file...

	type File_Type(Filename : String) is private;
	

Here you have to supply a filename if you want to open a file - but once
you have opened it, you don't necessarily want the filename any more.

Similarly you may want to initialize an index into a hash table, which
again requires a horrible long string, which is of no relavence once
the index value is calculated.

Dale




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Syntax for tagged record types
  1997-05-24  0:00 Syntax for tagged record types Robert Dewar
  1997-05-25  0:00 ` Matthew Heaney
@ 1997-05-27  0:00 ` Tucker Taft
  1997-05-27  0:00 ` Dale Stanbrough
  2 siblings, 0 replies; 6+ messages in thread
From: Tucker Taft @ 1997-05-27  0:00 UTC (permalink / raw)



Robert Dewar (dewar@merv.cs.nyu.edu) wrote:

: Matthew says

: <<I think that using discriminants as "constructor arguments" is a real
: kludge, and obfuscates declarations.  Ada 95 doesn't have constructors, so
: let's not try to fight the language.>>

: Most people find the use of discriminants as "constructor arguments" a
: natural and powerful feature in Ada (though naturally they don't think
: in terms of this terminology).

One important thing to keep in mind.  Discriminants are only arguments
to the "default-initializing constructor" (the default expressions for
the components plus the optional procedure Initialize).  If you 
have more complicated kinds of "explicit" initialization in mind, then by 
all means write a (parameterized) function or procedure to do the work.

Also, if you look at how constructors are used in other OO languages, you
will often find their parameters are used to control things like size
or data structure variant.  In these cases, you have a practically direct
match to the use of discriminants, even in the Ada 83 world.

--
-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Burlington, MA  USA




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Syntax for tagged record types
  1997-05-25  0:00 ` Matthew Heaney
  1997-05-26  0:00   ` Robert A Duff
@ 1997-05-27  0:00   ` Jon S Anthony
  1 sibling, 0 replies; 6+ messages in thread
From: Jon S Anthony @ 1997-05-27  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002505971422590001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes:

> In article <dewar.864485829@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:
> 
> >You can declare that "I think X is a kludge" for any X, but such a statement
> >is only helpful to discussion if you give some idea *why* you think this.
> 
> I say this because "discriminant" should mean "tag in a disjoint union." 
> Records are Cartesian product, and discriminated records are disjoint
> union.  And that's all discriminate record should mean.

So.  Where did you get this idea?  That is not even what Ada83 meant
by the term.  In Ada95 all sorts of things can have discriminants for
parameterization purposes: beater records (subsuming your one idea),
task types, protected types, and private types.  So, why do you say
"should" here?  What's your rationale for saying your notion is the
"way it _should_ be"????


> Respecting the spirit of the language means not using a discriminant as a
> constructor parameter.

IMO, this is just plain wrong.

> Norm stated in his book that "In Ada, the role of
> these [constructor] parameters can be played by discriminants." (p. 579) 
> Now, I like Norm, and I thank him a thousand times over every time I can
> pick up his book and answer a question, but this is horrible advice.  When
> you use a discriminant as a constructor parameter, the purpose of the
> discriminant is now ambiguous.

There is nothing whatsoever ambiguous about this.  A discriminant is a
declaration parameter.  _How_ it is used in the _implementation_ of
that declaration is NOT RELEVANT to the client.

>  And I the poor maintanence programmer have to figure out what you
> mean.  So I have to guess, and I might guess wrong.

Unless you are dealing with the implementation of the type, why are
you even thinking about how it is used???  You might as well be
concerned about the exact implementation details of an abstract hash
table used in the client program.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~1997-05-27  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-05-24  0:00 Syntax for tagged record types Robert Dewar
1997-05-25  0:00 ` Matthew Heaney
1997-05-26  0:00   ` Robert A Duff
1997-05-27  0:00   ` Jon S Anthony
1997-05-27  0:00 ` Tucker Taft
1997-05-27  0:00 ` Dale Stanbrough

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox