var
mybooks:= books.create;
Having filled the list (myList) with mybooks, I now want to sort the list by
RefNo. I just can't figure out how to define item1 and item2 in the
arguments of Compare! I have 3 very good Delphi books - no luck there, or in
the online help.
Thanks, Gord.
> Having filled the list (myList) with mybooks, I now want to sort the list by
> RefNo. I just can't figure out how to define item1 and item2 in the
> arguments of Compare! I have 3 very good Delphi books - no luck there, or in
> the online help.
The function needs to be a standalone function (not an instance
method) that take two pointers. You need to typecast them inside the
function to the 'books' type.
--
Marc Rohloff [TeamB]
marc -at- marc rohloff -dot- com
Since you are storing books instances, your items must be cast to
books. Inside the routine, you compare the RefNos:
function CompareBooks(item1, item2: Pointer): Integer;
begin
if books(item1).RefNo > books(item2).RefNo then
Result := 1
else if books(item1).RefNo < books(item2).RefNo then
Result := -1
else
Result := 0;
end;
Now you can pass CompareBooks to the Sort routine.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Death does not concern us, because as long as we exist, death is
not here. And when it does come, we no longer exist."
-- Epicurus.
> function CompareBooks(item1, item2: Pointer): Integer;
> begin
> if books(item1).RefNo > books(item2).RefNo then
> Result := 1
> else if books(item1).RefNo < books(item2).RefNo then
> Result := -1
> else
> Result := 0;
> end;
Or just:
function CompareBooks(item1, item2: Pointer): Integer;
begin
result := books(item1).RefNo - books(item2).RefNo;
end;
> Since you are storing books instances, your items must be
> cast to books.
Alternatively, declare the parameters to be "books" instead of "Pointer",
and then cast the function itself when passing it to Sort(), ie:
function CompareBooks(item1, item2: books): Integer;
begin
if item1.RefNo > item2.RefNo then
Result := 1
else if item1.RefNo < item2.RefNo then
Result := -1
else
Result := 0;
end;
myList.Sort(TListSortCompare(@CompareBooks));
Or:
var SortProc: TListSortCompare;
SortProc := @CompareBooks;
myList.Sort(SortProc);
Gambit
> On Tue, 29 Jan 2008 22:20:42 +0100, Rudy Velthuis [TeamB] wrote:
>
> > function CompareBooks(item1, item2: Pointer): Integer;
> > begin
> > if books(item1).RefNo > books(item2).RefNo then
> > Result := 1
> > else if books(item1).RefNo < books(item2).RefNo then
> > Result := -1
> > else
> > Result := 0;
> > end;
>
> Or just:
> function CompareBooks(item1, item2: Pointer): Integer;
> begin
> result := books(item1).RefNo - books(item2).RefNo;
> end;
FWIW, this was discussed in a thread last week: For sorting, and some
searches as well, it would already do if the test was only for
LessThan, instead of this test returning positive, zero or negative.
That would greatly simplify many of the tests:
function BooksLessThan(item1, item2: Pointer): Boolean;
begin
Result := books(item1).RefNo < books(item2).RefNo;
end;
--
Rudy Velthuis [TeamB] http://www.teamb.com
"If you want to make an apple pie from scratch, you must first
create the universe." -- Carl Sagan
> On Tue, 29 Jan 2008 22:20:42 +0100, Rudy Velthuis [TeamB] wrote:
>
> > function CompareBooks(item1, item2: Pointer): Integer;
> > begin
> > if books(item1).RefNo > books(item2).RefNo then
> > Result := 1
> > else if books(item1).RefNo < books(item2).RefNo then
> > Result := -1
> > else
> > Result := 0;
> > end;
>
> Or just:
> function CompareBooks(item1, item2: Pointer): Integer;
> begin
> result := books(item1).RefNo - books(item2).RefNo;
> end;
Yes, but that COULD overflow. It depends on the range of the RefNos
issued.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"All are lunatics, but he who can analyze his delusion is called
a philosopher." -- Ambrose Bierce (1842-1914)
Gord.
Gordon,
You may find the discussions started by Olivier Pons
in this same group on January 05, 2008 with subject
"TList and Sort" interesting.
Regards, JohnH
> Alternatively, declare the parameters to be "books" instead of "Pointer",
> and then cast the function itself when passing it to Sort(), ie:
>
> function CompareBooks(item1, item2: books): Integer;
> begin
> if item1.RefNo > item2.RefNo then
> Result := 1
> else if item1.RefNo < item2.RefNo then
> Result := -1
> else
> Result := 0;
> end;
Or, for when you can't change the functions parameter types:
function CompareBooks(Item1, Item2: Pointer): Integer;
var
B1: Books absolute item1;
B2: Books absolute item2;
begin
if B1.RefNo > B2.RefNo then
Result := 1
else if B1.RefNo < B2.RefNo then
Result := -1
else
Result := 0;
end;
With the above of course, you must be sure that Item1 and Item2 will always
be Books types.
--
Jay
Jason Burgon - author of Graphic Vision
http://homepage.ntlworld.com/gvision
> function CompareBooks(Item1, Item2: Pointer): Integer;
> var
> B1: Books absolute item1;
> B2: Books absolute item2;
I think any use of "absolute" is nasty.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"No Sane man will dance." -- Cicero (106-43 B.C.)
But why? What is the difference casting this way and casting after the begin
statement with
Books(Item1)
?
If Item1 or Item2 are not passed as type Books then there will be an error -
but that would be an error *anyway*.
Absolute is nothing more than a different method of casting.
--
Wayne Niddery - TeamB (www.teamb.com)
Winwright, Inc. (www.winwright.ca)
> (2) I am a little suspicious about what the compiler thinks that
> I am trying to do by using it and what kind of length checking the
> compiler will do
None whatsoever. The compiler does not assume anything and it does
absolutely (no pun intended) no checks.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"When I told the people of Northern Ireland that I was an
atheist, a woman in the audience stood up and said, 'Yes, but
is it the God of the Catholics or the God of the Protestants
in whom you don't believe?" -- Quentin Crisp.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flsyggun5pq...@rvelthuis.de...
> >
> >> function CompareBooks(Item1, Item2: Pointer): Integer;
> >> var
> >> B1: Books absolute item1;
> >> B2: Books absolute item2;
> >
> > I think any use of "absolute" is nasty.
>
>
> But why? What is the difference casting this way and casting after
> the begin statement with Books(Item1)
Not much, except that the compiler checks if the cast is possible and
sometimes performs some magic on an explicit cast like this. Absolute
does NOTHING of this.
I guess that is why absolute is, for instance, not possible in .NET,
while a normal cast is.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"All our knowledge merely helps us to die a more painful death
than animals that know nothing." -- Maurice Maeterlinck.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote
>> I think any use of "absolute" is nasty.
"Wayne Niddery (TeamB)" <wnid...@chaffaci.on.ca> wrote
> But why? What is the difference casting this way and
> casting after the begin statement with
> Books(Item1)
My complaints with the use of "absolute" are
(1) I do not think that the Help description is sufficient.
(2) I am a little suspicious about what the compiler thinks that
I am trying to do by using it and what kind of length checking the
compiler will do . For example, can the compiler distinguish
between my intentions to refer to the value or address. And what
will happen, if the compiler has decided to make the target variable
a register.
Because of this, I restrict my use the "absolute* directive to cast
function and procedure parameters between pointer types only.
--JohnH
> Not much, except that the compiler checks if the cast is possible and
> sometimes performs some magic on an explicit cast like this. Absolute
> does NOTHING of this.
Given:
function Compare (item1, item2:pointer):integer;
the statement 'books(item1).RefNo' does *not* check if the cast is
possible or even if the pointer is an object. I don't know what magic
you are referring to.
The only advantage of a hard typecast over absolute is that the
typecast checks that the source is the same size as the destination.
> And what
> will happen, if the compiler has decided to make the target variable
> a register.
The compiler handles this situation correctly.
> On Wed, 30 Jan 2008 17:45:58 +0100, Rudy Velthuis [TeamB] wrote:
>
> > Not much, except that the compiler checks if the cast is possible
> > and sometimes performs some magic on an explicit cast like this.
> > Absolute does NOTHING of this.
>
> Given:
> function Compare (item1, item2:pointer):integer;
>
> the statement 'books(item1).RefNo' does not check if the cast is
> possible or even if the pointer is an object. I don't know what magic
> you are referring to.
I know. I am generally against using "absolute". In this case, there is
no difference, but there are cases where there is one. Just see what
happens if you cast item1 to a Double, or to a six byte record. I agree
it is not much, but it is a check.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Before C++ we had to code all of our bugs by hand; now we
inherit them." -- unknown
| I think any use of "absolute" is nasty.
I don't. <giggle>
--
Q
01/30/2008 10:28:25
XanaNews Version 1.17.5.7 [Q's Salutation mod]
> Marc Rohloff [TeamB] wrote:
>
> > On Wed, 30 Jan 2008 17:45:58 +0100, Rudy Velthuis [TeamB] wrote:
> >
> > > Not much, except that the compiler checks if the cast is possible
> > > and sometimes performs some magic on an explicit cast like this.
> > > Absolute does NOTHING of this.
> >
> > Given:
> > function Compare (item1, item2:pointer):integer;
> >
> > the statement 'books(item1).RefNo' does not check if the cast is
> > possible or even if the pointer is an object. I don't know what
> > magic you are referring to.
>
> I know. I am generally against using "absolute". In this case, there
> is no difference, but there are cases where there is one. Just see
> what happens if you cast item1 to a Double, or to a six byte record.
> I agree it is not much, but it is a check.
FWIW, I am not very fond of "hard" casts either, e.g. books(item1). In
C++, there are a few explicit cast types I'd like to see in Delphi. OK,
we have two of them: dynamic casts and reinterpret casts. But only the
dynamic cast is done with a keyword: as. The reinterpret cast (Delphi's
"hard" cast) is already hard to find, since it has the syntax of a
function call. The static cast is also like a hard cast, but provides a
few sanity checks.
But in C++ all these casts can be done using keywords. This makes them
easy to find and easy to distinguish.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"I begin by taking. I shall find scholars later to demonstrate
my perfect right."
-- Frederick (II) the Great
The same thing that would happen if you used the wrong variant within a
variant record definition. Bad things *can* happen. Should variant records
be banned too?
Not on plain pointer types. Generally not on much else either.
> > Not much, except that the compiler checks if the cast is possible
> > and sometimes performs some magic on an explicit cast like this.
>
> Not on plain pointer types. Generally not on much else either.
Even on plain pointer types. It checks, for instance, the sizes. Try to
cast a pointer to a Double or a record which is > 4 bytes in size and
see what happens.
You can cast a plain pointer to an Int64 without error, but that is
only because the pointer is interpreted as integer and is then expanded
to 64 bits.
Absolute does not offer ANY check. Nothing. Nada. It will let you
overwrite memory, or the return stack, without any problems. As you can
see in the program below, casting to PR or to Double fails.
program CastTest;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
PR = packed record
A, B, C: Word;
end;
procedure Test;
var
W: Integer;
X: Pointer;
Y: Integer;
Z: Integer;
A: Double absolute X; // no error
B: Double;
I: Int64 absolute X;
J: Int64;
P: PR absolute X;
Q: PR;
begin
X := Pointer($87654321);
W := $55AA55AA;
Y := $33773377;
Z := $11991199;
Writeln(Format('%.16x', [I]));
Writeln(Format('%.4x %.4x %.4x', [P.A, P.B, P.C]));
// to avoid optimizing out W, Y, Z
Writeln(Format('%.8p %.8p %.8p %.8p %.8x %.8x %.8x',
[@W, @X, @Y, @Z, W, Y, Z]));
J := Int64(X);
Writeln(Format('%.16x', [J]));
Readln;
// B := Double(X); // error
// Q := PR(X); // error
end;
begin
Test;
end.
FWIW, note how the D2007 compiler arranges the variables in memory. At
the lowest address comes Z, then Y, then W and finally X. Adding more
variables lets them grow downward even more.
Now, if you want a crash, simply "absolute-cast" X to a bigger array of
char and fill that with enough characters.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Opportunities multiply as they are seized." -- Sun Tzu
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flt5xfux93z...@rvelthuis.de...
> >
> > Just see what
> > happens if you cast item1 to a Double, or to a six byte record. I
> > agree it is not much, but it is a check.
>
>
> The same thing that would happen if you used the wrong variant within
> a variant record definition. Bad things can happen. Should variant
> records be banned too?
No, but they should IMO not be used to cast one type to another, unless
you really want to play dirty. That is not what they were meant for.
IMO, that is "clever coding".
Variant records were required when people wanted to pass the same type
but had to pass different information internally, IOW, as some kind of
poor man's polymorphism, with different items overlapping to save
precious bytes. If space had not been an issue, one could just as well
have used non-variant records.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Biologically speaking, if something bites you it's more likely
to be female." -- Desmond Morris.
"Marc Rohloff [TeamB]" <ma...@nospam.marcrohloff.com> wrote
> The compiler handles this situation correctly.
Marc, where you be, if I have a problem? <G> Again, I would be
a little more assured, if Help had a better explanation.
--JohnH
That's *exactly* what they were designed for!
A perfect example is the VCL definition of TMessage in order to allow access
to wparam and lparam in different ways. Variant records are also used very
well in, for example, handling EDI records - yes it could be done
differently, but it is exactly the klind of thing where variant records (or
C Unions) shine.
> Variant records were required when people wanted to pass the same type
> but had to pass different information internally, IOW, as some kind of
> poor man's polymorphism, with different items overlapping to save
> precious bytes. If space had not been an issue, one could just as well
> have used non-variant records.
It wasn't just space, it was easier coding and cleaner algorithms. There is
nothing *dirty* about it. Again using the VCL TMessage definition as an
example, any version of handling that without using the variant would result
in a *ton* more code that was, in fact, harder to follow and maintain as
well as less efficient in execution.
*Any* code that works with pointers is subject to such errors, period.
Features like variant records and absolute address aliasing do not make this
any worse.
And yes, that is a reason languages and best practices have moved away from
explicit pointer management to a great extent - for the vast majority of
coding, dealing with the underlying pointers just isn't necessary and so
code is improved by allowing developers to code against the objects instead
of explicitly against the memory addresses where they reside. However, that
does not mean working directly with pointers is *always* unnecessary or can
be avoided, and *sometimes* using pointers is the right way to go. In those
cases, the above features are as valid as any other and no more dangerous.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fltsdrvalcm...@rvelthuis.de...
> >
> > No, but they should IMO not be used to cast one type to another,
> > unless you really want to play dirty. That is not what they were
> > meant for. IMO, that is "clever coding".
>
> That's exactly what they were designed for!
Not at all. No way. They were designed by Wirth to allow a record to
have different contents, depending on a switch value, the case selector
(or tag). The case selector in original Pascal was always an existing
field, not some pseudo one like "case Boolean of" or "case Byte of".
IOW, this was some crude poor man's polymorphism. I don't even know if
there is a guarantee that the parts overlap.
Only much much later, it was discovered (and abused) in BP and Delphi,
that nothing prevented you from writing to one and reading from another
overlapping part.
http://www.moorecad.com/standardpascal/iso7185.pdf
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Do illiterate people get the full effect of alphabet soup?"
-- John Mendoza
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flts6svab8y...@rvelthuis.de...
> >
> > Absolute does not offer ANY check. Nothing. Nada. It will let you
> > overwrite memory, or the return stack, without any problems. As you
> > can see in the program below, casting to PR or to Double fails.
>
>
> Any code that works with pointers is subject to such errors, period.
> Features like variant records and absolute address aliasing do not
> make this any worse.
Any code circumventing type security, be it code using casts, absolute
or code using the effect that variant parts of a record overlap, is
problematic. But if we must use a cast, absolute is the worst of all
possible choices, together with the (ab)use of variant records. Hard
casts at least offer some limited safety, even when used on pointers.
Dynamic casts ("as" or "is") offer even more type safety.
That is why I think that absolute is a very bad thing. I also think
that abusing variant records is a "clever" trick, relying on internals,
and not one bit better.
Oh, sometimes one MUST use such tricks, if one is interested in the
internals. But it is not good code, IMO.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"... one of the main causes of the fall of the Roman Empire was
that, lacking zero, they had no way to indicate successful
termination of their C programs." -- Robert Firth
> The case selector in original Pascal was always an existing field,
> not some pseudo one like "case Boolean of" or "case Byte of".
Not so. I don't have "User Manual and Report" at hand right now (it's
in storage at home), but I started with Pascal in 1974-5, and I
distinctly remember our confusion over "tag fields that didn't even
exist".
The document you refer to says more or less the same, did you read it?
>>>6.4 .3.3 Record-types
>>> ...
>>> variant-selector = [ tag-field ` :' ] tag-type .
--
Anders Isaksson, Sweden
BlockCAD: http://web.telia.com/~u16122508/proglego.htm
Gallery: http://web.telia.com/~u16122508/gallery/index.htm
> Rudy Velthuis [TeamB] wrote:
>
> > The case selector in original Pascal was always an existing field,
> > not some pseudo one like "case Boolean of" or "case Byte of".
>
> Not so. I don't have "User Manual and Report" at hand right now (it's
> in storage at home), but I started with Pascal in 1974-5, and I
> distinctly remember our confusion over "tag fields that didn't even
> exist".
>
> The document you refer to says more or less the same, did you read it?
That is the current standard. Wirth did not start with that standard. I
don't know where I read it, but I do remember that in early Pascal, a
tag field was always a field.
But that is not too important anyway. The main reason for variant
records was some kind of poor man's polymorphism, and NOT the
overlaying of items so you could "cast" from one to the other. The
standard does not even mention anywhere that the memory parts must
overlap, AFAICS. This is, AFAIK, merely an implementation detail of TP
and Delphi, which, of course, nicely coincides with C unions.
But the standard says:
<<
An access to a component of a variant of a variant-part, where the
selector of the variant-part is not a field, shall attribute to the
selector that value associated (see 6 .4 .3.3) with the variant . It
shall be an error unless a variant is active for the entirety of each
reference and access to each component of the variant.
When a variant becomes non-active, all of its components shall become
totally-undefined.
NOTE | If the selector of a variant-part is undefined, then no variant
of the variant-part is active.
>>
IOW, you are only allowed to access that variant part that is active,
and the otehr variant parts are undefined. So the trick of writing to
one variant part and then reading it from another is, in that standard,
undefined behaviour. And, if the parts do not even have to overlap, it
is plain useless as well.
This does, IMO, clearly demonstrate that the reason for variant records
is the crude polymorphism I mentioned, and most definitely not the
casting trick, as Wayne claimed.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"I admire the Pope. I have a lot of respect for anyone who can
tour without an album." -- Rita Rudner.
Wrong - and clearly not supported by the link you provide (iso7185) - it
shows that the tag *is optional*:
variant-part = `case' variant-selector `of' variant f ` ;' variant g .
variant-selector = [ tag-field ` :' ] tag-type .
See the square brackets around "tag-field" - that means optional Rudy.
> IOW, this was some crude poor man's polymorphism. I don't even know if
> there is a guarantee that the parts overlap.
I'm not sure what hair you are trying to split, because I don't see one. You
are, I'm afraid, ignorant of the uses of variant records (I mentioned one,
EDI, where they are very useful and, in order to be so, need the very things
you are critizing in your above statement.
The purpose of variant records is *precisely* to overlay the same memory
space with different variable or record defintions. Explicitly failing to
specify "packed" in a variant record definition simply indicates one does
not know why one is using a variant as it defeats the purpose and subjects
one to depending on luck for it to work - whatever alignment the compiler
imposes.
It is also *critical* for the programmer to be able to decide whether the
case selector is part of the record or whether he needs some other method to
determine which variant to use. For EDI (an early and heavily used "business
to business" data transfer mechanism) or similar purposes, the detailed
definition of the EDI records must be *modelled* by the programmer, not
*decided* by him. If the EDI record defines the method of determining what
kind it is (usually a record number in the form of a fixed length string)
that is not usable by the Pascal Case selection, then forcing it to have an
actual field for that selector would make variants *impossible* to use for
this purpose - not just difficult, but *impossible*, there would be no way
to model the incoming data correctly.
Absolute does *precisely* the same thing, analogous to the variant with the
pseudo-tag - it is left to the programmer to provide the means to determine
which "variant" is to be used in a given case. If, within the context of a
method, one knows what the types are that will be passed, or knows how to
determine thoses types, then there is nothing "dangerous" about using
absolute. It is simply the responsibility of the programmer to understand
what s/he is doing, which is *always* the case. I hope you don't try to
object to absolute on the basis that Wirth did not include it in the
original language, you'll slip quickly on that slope.
> Only much much later, it was discovered (and abused) in BP and Delphi,
> that nothing prevented you from writing to one and reading from another
> overlapping part.
That's silly Rudy, something that obvious could not have been overlooked
from the very beginning. Do you really think Wirth or any of his colleagues
were that stupid? From the link you give below, it is clear the intention
was that only one variant of a variant definition should be "active" at a
time and it would be an error for one part to be active if the selector
specified another (and this would conform to typical use such as the EDI
example I use here), but to my knowledge, no version of Pascal has *ever*
had any mechanism for signifying, let alone enforcing, what part of a
variant is "active" and thus no way for an error to be raised if the
programmer let this situation occur. So yes, the possibility of using it as
a means of translation (writing to one/reading from another variant) was
clearly understood and always existed.
> http://www.moorecad.com/standardpascal/iso7185.pdf
The fact that a mechanism is discovered to be useful in a context apart from
the original intent of a feature is not a bad thing or something to be
avoided. That Wirth may not have intended variant records to be used to
translate or re-interpret data does not make it an "abuse" to do so. Such
additional uses of things originally designed for something else is very
common, not just in computer, but in all industries - for example it is
often discovered a drug designed to treat one thing is effective for
something else. Should such use be banned just because the original designer
did not "intend" for that new use? That would be ludicrous - and in the
field of medicine, fatal for people that could otherwise be treated.
Ah, so now there is some doubt on this specific, it is no longer important.
> The
> standard does not even mention anywhere that the memory parts must
> overlap, AFAICS. This is, AFAIK, merely an implementation detail of TP
> and Delphi, which, of course, nicely coincides with C unions.
Rudy, without the variant parts of a record overlapping there would
essentially be no purpose whatever to even define such a construction. The
*entire* purpose, just as with unions in C, is to overlay the *same* emmory
with different defintions. Each variant is supposed to begin at the exact
same offset within the record. That they didn't spell it out does not
contradict or put this in doubt because that the time the spec was written,
"packed" was the default - compilers compiled exactly what the programmer
specified and did not impose any other alignment (at least no *undocumented*
alignment so that the programmer could code accordingly). Without this, as
per my other post, use of variant records would not really be possible since
their purpose was to allow modelling of incoming already existing data
structures.
> But the standard says:
>
> An access to a component of a variant of a variant-part, where the
> selector of the variant-part is not a field, shall attribute to the
> selector that value associated (see 6 .4 .3.3) with the variant . It
> shall be an error unless a variant is active for the entirety of each
> reference and access to each component of the variant.
>
> When a variant becomes non-active, all of its components shall become
> totally-undefined.
See my other post.
> > Not at all. No way. They were designed by Wirth to allow a record to
> > have different contents, depending on a switch value, the case
> > selector (or tag). The case selector in original Pascal was always
> > an existing field, not some pseudo one like "case Boolean of" or
> > "case Byte of".
>
> Wrong - and clearly not supported by the link you provide
Wayne, that may be, in that standard, it was not true in Wirth's
Pascal. Not that it is crucial to what I wrote. It was meant as one
piece of evidence.
And believe me, the casting trick was NOT the reason for variant parts.
The variation in data was the reason for this: you have a common record
type that can have several different shapes. That was the sole reason
for variant records.
Example:
type
customertype = (person, company);
customer = record
case custtype: customertype of
person: (name: string);
company: (name: string; contactperson: string);
end;
Note that there were no objects, no inheritance, and this was the
closest they could get to polymorphism. This way you could pass a
customer, and depending on the type of customer, different sets of data
were available.
Note that Wirth also used them in Modula-2, and on.
One nice explanation:
http://www.arjaybooks.com/Modula-2/Text/Ch11/Ch11.7.html
I think that article clearly underlines what I have been saying.
Anyway, if overlapping had been the main reason, then why does the
standard not even mention it once? It should make it mandatory, for the
trick to work.
Also note that the trick only works in Delphi if the record is packed.
If overlapping was the standard, that should not be required either.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"While we are postponing, life speeds by."
-- Seneca (3BC - 65AD)
Again because that was the entire point of being able to define variant
records - *exactly* for the same reason of providing unions in C. Are you
going to argue the C unions were not meant to have overlapping definitions -
i.e. structures that *redefine* the same space?
> Also note that the trick only works in Delphi if the record is packed.
Of course.
> If overlapping was the standard, that should not be required either.
The packed keyword also exists for a reason - the programmer was expected to
determine when and why it should be used or not. That the compiler doesn't
force its use just because one defines a variant structure does not support
your assertions.
At the time of these standards, programmers (who could generally only become
so by spending a few years gaining a Computer Science university degree)
were expected to know the use of such things as packed and when it should be
applied or not. There was absolutely nothing considered wrong, especially at
that time, with a programmer understanding and taking advantage of his
knowledge of alignment (or lack of it) performed by the language/compiler he
was using. In general though, it makes no sense to define a variant record
that is not packed, such would only be a very rare exception.
What you continue to not recognize was the nature of most programming at
that time. The main purpose of records was not for application-internal use
(though of course they were used for that as well), their main purpose was
for *input and output*. That input and output had to be made compatible
across a large variety of hardware that did not have as universal standards
as has evolved until today - even the number of bits in a byte varied, let
alone alignment and so on. Therefore any programmer defining a record
intended for exchange with any other process was making a grave error in not
*packing* his record structures. Variant record definitions were of very
little use *internally* even with the small amounts of memory available at
that time, their use was *also* predominately to accomodate data exchange
between processes and systems. Data came in on cards or tape and conserving
space on those mediums was as crucial as conserving memory. Even with early
electronic transmission, slow speeds dictated packing data as tightly as
possible.
Using the fact that it was possible to define variant records that were not
packed to bolster your argument is foolish and completely without any
factual basis. *Packed* variant records were crucial in both the physical
exchange of data, and the processing of it on systems having as little as
*4K* of memory.
Today the *need* for variant records is a lot less, but that makes them no
less useful in certain circumstances. But today's availability of gigs of
memory and bandwidth cannot be used as a basis for arguing what was intended
for a feature back then, and that is basically what you are doing here.
There is *no other purpose* of a variant record than to redefine the *same*
memory space with different definitions. Give me one use or advantage a
variant record provides if its variant components do *not* overlap. I really
doubt you can come up with one I can't show to be contrived and better done
without variants. Wirth included variants for a reason.
> Again because that was the entire point of being able to define
> variant records - exactly for the same reason of providing unions in
> C. Are you going to argue the C unions were not meant to have
> overlapping definitions - i.e. structures that redefine the same
> space?
C Unions most definitely have. But nothing says variant records should.
The main reason was the poor man's polymorphism, i.e. one type can have
different shapes. It is irrelevant if the variant parts overlap.
Actually, these do not overlap:
type
NoOverlap = record
case Selector: Word of
0: (ID: Smallint);
1: (Name: string);
end;
Just look at the offsets of the fields, either in the CPU window or in
a simple test program.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Be nice to people on your way up because you meet them on your
way down." -- Jimmy Durante
You can assert this as often as you like, it won't make it true. That was
absolutely *not* the reason Wirth devised variant records!
To be more clear, it was intended for polymorphism in a strict *data*
sense - multiple defintions over the *same memory space*, not in the
object-oriented sense. Polymorphism in the OO sense means many *behaviours*
and is typically implemented via inheritance of by interfaces.
If you claim you mean in the data sense, then it would show even more you
don't know what you are talking about - what is polymorphic about data
definitions if they *don't* define the same memory space?? If there is no
overlap (or at least no guaranteed overlap) then what purpose does a variant
record serve? What then is the advantage of a variant over separtely defined
records? What does such "polymorphism" accomplish? Show me some sensible way
it would be used in code.
> You can assert this as often as you like, it won't make it true. That
> was absolutely not the reason Wirth devised variant records!
Indeed. It is even true if I don't assert it at all. It was the sole
reason Wirth devised variant records. Note that Pascal was meant as a
teching language, and the strict type checking Wirth imposed on Pascal
made this the only way to have different contents for the same type.
Like the example given in the iso7185.pdf:
record
x, y : real;
area : real;
case shape of
triangle :
(side : real ; inclination, angle1, angle2 : angle);
rectangle :
(side1, side2 : real ; skew : angle);
circle :
(diameter : real);
end
This is the classical example of polymorphic shapes. But NOT ONE WORD
about the memory layout, overlapping fields, etc. If overlaps were the
main or sole reason, their use for this would at least be MENTIONED and
the overlapping memory layout would be specified in fine detail, just
like the rest of the standard. It would also have been in the example
given for variant records. But instead, you see the above.
In an earleir post, you gave TMessage as an exsample. Well, it is clear
that Borland has used the overlapping fields trick more than once, and
I'm sure this will not change, in Delphi. But it was not the reason for
Wirth to do this in Pascal.
I think I have given ample evidence why I am right.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"How can I lose to such an idiot?"
-- A shout from chessmaster Aaron Nimzovich (1886-1935)
So now without those variant components overlapping, what value is this
record definition over having *separate* record definitions for the three
shapes? The whole point is to redefine the same memory space. In an era
where every byte of space in data *storage* as well as computer memory,
counted crucially, it would be unconscionable to write out records that
might have undefined gaps due to implicit alignment. Thus such an example as
the above would be unusable in any practical sense as one could only gain
the effiiciency needed by separating this variant into distinct packed
records.
The fact that Wirth developed Pascal as a teaching language changes nothing
since his goal was to teach good programming practices *that could actually
be employed* when working in this or any other language - and in this case
that would mean, for example, making good use of C unions!
If you object that the spec should then have specified packed for the above
example, that would be nonsense as this is a language specification, not a
use specification and "packed" is properly covered in other parts of the
spec (see structured types to see it can be applied to records).
> To be more clear, it was intended for polymorphism in a strict data
> sense - multiple defintions over the *same memory space*, not in the
> object-oriented sense.
The standard does not specify that variant parts occupy the same
memory. If that was a requirement, or the main goal, it should at least
be MENTIONED.
I do not say it is not true in most implementations, and I do know it
is true for PACKED records in Delphi. It is not generally true for
records in Delphi.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Raymond's Law of Software: Given a sufficiently large number of
eyeballs, all bugs are shallow." -- Eric S. Raymond
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fly1y4puco...@rvelthuis.de...
> >
> > Like the example given in the iso7185.pdf:
> >
> > record
> > x, y : real;
> > area : real;
> > case shape of
> > triangle :
> > (side : real ; inclination, angle1, angle2 : angle);
> > rectangle :
> > (side1, side2 : real ; skew : angle);
> > circle :
> > (diameter : real);
> > end
>
>
> So now without those variant components overlapping, what value is
> this record definition over having separate record definitions for
> the three shapes?
Polymorphism.
Assume the type is called graphicshape:
type
graphicshape = record
x, y : real;
etc...
end;
procedure drawshape(s: graphicshape);
begin
case s.shape of
triangle:
drawtriangle(s);
rectangle:
drawrectangle(s);
circle:
drawcircle(s);
end;
Also:
shapes: array[1..1000] of graphicshape;
for i := 1 to 100 do
drawshape(shapes[i]);
How would you otherwise put different shapes into the same array and
pass them to the same routine?
I think that is a classical example of (crude) polymorphism.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"If you give a man a fish, he will eat for today. If you teach
him to fish, he'll understand why some people think golf is
exciting." -- P.G. Wodehouse
Why? Packed was documented elsewhere in the spec. It is a language spec, not
a user guide.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fly2azq7qj...@rvelthuis.de...
> >
> > The standard does not specify that variant parts occupy the same
> > memory. If that was a requirement, or the main goal, it should at
> > least be MENTIONED.
>
> Why? Packed was documented elsewhere in the spec. It is a language
> spec, not a user guide.
What has packed got to do with it?
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Giving birth is like taking your lower lip and forcing it over
your head." - Carol Burnett.
Data-wise, sure, but you are still ignoring the crucial elements and history
of the vast majority of programming at that time. The vast majority of
programs were batch processes - they would read a record from input, process
it, and write another record out. Period. As I've tried to convey several
times already, every byte was crucial and the purpose of Pascal variants, as
with C unions, was to be able to model variable data I/O with such space
efficiencies a major concern.
For that external data input, there would *not be any implicit or
undocumented gaps, not even one byte* between defined fields. In writing
such records, one would not *dare* be so sloppy as to write records with
implicit or undefined gaps between fields just because the default alignment
of a compiler might want to impose it. What you defined as a record in your
program and what appeared in storage (whether cards, tape, or disk) *better
match exactly*, any mismatch was an error by definition. Such record
definitions when defined to represent data storage had to do just that - be
a faithful and exact model of it so a program could read that data and
directly access the field elements with that record defintion. There was no
mapping via moving or copying fields, that would take too many expensive
cycles.
Insisting that overlapping in a variant record wasn't necessary or expected
is to deliberately ignore the entire context of the times in which the
language was first defined and the then expected needs of *data processing*.
You're assertions as to the purpose of variants is based on much later
standards where every byte is no longer concerned. You cannnot impose such
standard retroactively ans assume that's how Wirth or others thought at that
time.
From the same site you linked to, about the CDC 6400 Wirth designed Pascal
for initially:
"The CDC 6400 could not address individual bytes, but was a (60 bit) word
only machine. Hence, Pascal's emphasis on packed types, packed strings, and
the pack/unpack procedures."
IOW, while he made it possible to define unpacked structures to allow more
flexibility, packed was expected to be used in most cases. You had to have a
reason *not* to use it, not the reverse.
Finally, to cement my case, from
http://www.moorecad.com/standardpascal/iso7185rules.html:
===
var vr: record
a: integer;
case b: boolean of { variant }
true: (c: integer; d: char);
false: (e: real)
{ end }
end;
Variant records allow the same "collection of types", but introduce the idea
that not all of the components are in use at the same time, and thus can
**occupy the same storage area**.
===
(My emphasis above)
And a bit further down:
"If the compiler chooses to implement variants, the total size of the
resulting record will be no larger than the fixed record parts plus the size
of the largest variant."
Hmm, sounds exactly like the definition of a C union, doesn't it?
Are you now going to argue that iso7185rules.html is wrong and you are
right??
> Finally, to cement my case, from
> http://www.moorecad.com/standardpascal/iso7185rules.html: ===
> var vr: record
>
> a: integer;
> case b: boolean of { variant }
>
> true: (c: integer; d: char);
> false: (e: real)
>
> { end }
>
> end;
>
> Variant records allow the same "collection of types", but introduce
> the idea that not all of the components are in use at the same time,
> and thus can **occupy the same storage area**. === (My emphasis
> above)
That is a comment by a certain Mr. Moore. And indeed, in most
implementations it is true that the parts overlap, to save space. Makes
perfect sense. But THE STANDARD DOES NOT SPECIFY IT, so one can not
assume that ALL implementations do it.
Note also that he says CAN, not MUST. For the casting trick to work,
they MUST occupy the same space.
But even then, if one wanted better memory usage, specifying different
records for each usage would even be better, then. One could even omit
the tag field. The main reason they are all in THE SAME TYPE is
polymorphism, i.e. the ability to pass ONE TYPE with varying data.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Having the source code is the difference between buying a house
and renting an apartment." -- Behlendorf
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fly2y6r5be...@rvelthuis.de...
> >
> > I think that is a classical example of (crude) polymorphism.
>
>
> Data-wise, sure, but you are still ignoring the crucial elements and
> history of the vast majority of programming at that time.
And you were there? <g>
--
Rudy Velthuis [TeamB] http://www.teamb.com
"The power of accurate observation is frequently called cynicism
by those who don't have it."
-- George Bernard Shaw (1856-1950)
Right, as I thought, you will continue to argue you are right and that a
certain Mr. Moore, who wrote this at the time and whose works is accepted in
the industry, is wrong.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flyk1k1eb53...@rvelthuis.de...
> >
> > That is a comment by a certain Mr. Moore. And indeed, in most
>
>
> Right, as I thought, you will continue to argue you are right and
> that a certain Mr. Moore, who wrote this at the time and whose works
> is accepted in the industry, is wrong.
I'm not saying he is wrong. I don't see him, or anyone else, not even
the standard, confirm what you claimed at the start of this thread:
that the main and original purpose of variant records is the ability to
use the casting trick(*) (and a trick it is, no more). What I do see is
that all examples of variant records in several publications, even in
the standard, all confirm what I am claiming: the variant record is a
crude form of polymorphism, and was never intended to be abused for the
casting trick.
Of course it makes sense that, in times when memory was not abundant
yet, variant parts overlapped. In fact, variant records were a way to
assemble various different memory layouts as ONE TYPE. There is nothing
wrong with that. But that does not mean that this overlap was
specifically done to make the casting trick possible. Actually, the
overlap is, if mentioned at all, only mentioned casually. That was a
side effect of many of the implementations, but certainly not the main
purpose.
---
(*) To reclaim:
I wrote:
>No, but they should IMO not be used to cast one type to another, unless
>you really want to play dirty. That is not what they were meant for.
>IMO, that is "clever coding".
You replied:
That's exactly what they were designed for!
--
Rudy Velthuis [TeamB] http://www.teamb.com
"I admire the Pope. I have a lot of respect for anyone who can
For a lot more of it then you. I first learned to program in Fortran in
1971.
A little more history....
COBOL, around since 1960, also had its equivalent to variant records/unions.
You could redefine the same memory with multiple data structures using
RENAMES (I worked with COBOL for 2 years at a bank). RENAMES is actually
closer to the Pascal Absolute directive since it was a separate structure
definition directed to overlay a previous one. I can guarantee you that
RENAMES really did directly and reliably overlay the same memory, it was
*required* that it do so.
ALGOL, though harder (for me at least) to follow its specification (I've
never looked at ALGOL code or the spec before), also appears to support
multiple definitions for the same memory space using a TAG. Note that both
Pascal and C are descendants of ALGOL, which of course built on previous
languages as well.
IOW there was industry precedent for this kind of structuring, it was not
new to either Pascal or C (and K & R were not uncognizant of Pascal when
they *later* developed C).
Do you think Wirth (and K & R in designing C) were uncognizant of these
other languages (especially, for Wirth, in regard to ALGOL!)? Do you think
Wirth would construct a language intended to teach programming that
contradicted what the normal and accepted conventions of other commonly used
languages were and the best practices of the day? Claiming that Wirth never
intended that variants *necessarily* overlay the same memory because it
wasn't explicitly specified ignores that this was already a common feature
for languages at that time and so was *assumed* It would only have had to be
specified if he had intended it *not* to be the case, i.e. departing from
already accepted convention.
You're assertions are contradicted by *much* history Rudy, not just my
counter-assertions.
Whether Wirth intended variants to allow translation between them or not
*might* be arguable (but not much). Whether he intended the structure to
reliably redefine the same memory is not.
As to the former, the tag was intended to identify which variant was
"active", but the tag was also assignable, so to switch variants, while
staying within the rules of "active" one merely needs to assign values to
one variant, set the tag to another variant index to make that variant
active, and then access the previously written variables via the now current
variant. In the case of omitting the tag, then of course what was "active"
is whichever variant you care to access. You are correct that the tag
variable was made optional sometime after 1970 - it was changed *for a
reason*.
IOW, the tag convention was not designed to say a variant record could only
be set *once* to one of the variants and then that record was forever only
that one variant; the tag was simply a means of *identiifying* which variant
was currently active so that the values could be accessed accordingly. It
was still left to the programmer to *know what he was doing*. If you think
that Wirth would not have considered that such a construction would be used
to perform translations of data then you insult Wirth's intelligence - he
was not that shortsighted or inexperienced!. Indeed the term "variant" can
only have a logical meaning in the context of representation, i.e. *variant
representations of the same data* - there is no other meaning of the term,
definitions that *follow* one another are not variants of each other! Words
have specific meaning, and people of Wirth's skill and education would use
such words very precisely in the design of a language.
Once again one major purpose of variants was to define data read in from
external sources. That incoming data would have a header and then some set
of fields, and those fields would be packed. What use would a variant
definition be if it could not be made to match that incoming data in all
*its* variants?
Insisting you know better, despite so much history, precedent, accepted
meaning of terms like "variant", and actual use, not to mention logic, that
demonstrates otherwise, is *blind arrogance*.
???
There have always been two parts to this discussion - the overlaying of the
variant definitions, and the uses for that. I've *never* said the *main*
purpose of overlaying the definition was for casting. Indeed I've been
focusing far more on the issue of data processing and being able to
read/write *variant data* from storage/external sources (repeatedly giving
you the example of EDI).
I have said that casting is *also* a use and have argued that there was
never an intention that it not be allowed or that it was considered wrong by
Wirth or anyone else at the time (as part of defending the Absolute
directive). It was never considered by them to be a "trick" or a "hack", it
was a common feature of many languages to be able to interpret the same
memory locations with different record structures.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flyx971wa69...@rvelthuis.de...
> > I'm not saying he is wrong. I don't see him, or anyone else, not
> > even the standard, confirm what you claimed at the start of this
> > thread: that the main and original purpose of variant records is
> > the ability to use the casting trick(*)
>
> ???
> There have always been two parts to this discussion - the overlaying
> of the variant definitions, and the uses for that.
Should repeat again what you said? You said variant records were
created for the casting trick.
This entire thread was about absolute and other tricks to re-interpet
values, like the variant record trick.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"One morning I shot a bear in my pajamas. How it got into my
pajamas I'll never know."
-- Groucho Marx
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flykq61faps...@rvelthuis.de...
> >
> > And you were there? <g>
>
>
> For a lot more of it then you.
I meant when Wirth designed Pascal and taught it at the THE in Zurich?
<g>
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Cole's Law: Thinly sliced cabbage."
The portion of it discussing Absolute, yes. Such "trick" as you insist on
calling it, was understood to be possible from the start - Wirth would
definitely have been aware of being able to use it that way (whether or not
he actually approved of it I have no idea, but he *allowed for it*), never
did I claim it was the *main purpose*.
Data processing is the main purpose of variant records.
Since then it has mainly been about your assertion that there was no
intention by the orignal language design that variants were intended to
overlay the same memory. I gave you example after example, precedent, and
references, to explain and demonstrate otherwise, yet you still insist you
know better. Overlaying the same memory is *required* in order to fulfil the
purpose of the feature - to read and write variant data schemes such as
EDI - a *data-wise* "polymorphism" as I already agreed. Using it as a
translation is a *consequent* possibility of that, one that Wirth could not
*possibly* have not foreseen.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0flzfns241q9...@rvelthuis.de...
> >
> > This entire thread was about absolute and other tricks to
> > re-interpet values, like the variant record trick.
>
>
> The portion of it discussing Absolute, yes. Such "trick" as you
> insist on calling it,
Yes, I do, and I think that is the only proper name for it.
> was understood to be possible from the start -
> Wirth would definitely have been aware of being able to use it that
> way
Taking into account what I have heard and read about Wirth, he would
firmly be opposed to such a trick. Heck, he did not even provide a way
to find out the size of a structure (no sizeof) or do bitwise
operations (note that and/or/not were reserved for Booleans, and xor
did not even exist) except with sets. He also did not provide for casts
or anything else low level.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"They say such nice things about people at their funerals that it
makes me sad that I'm going to miss mine by just a few days."
-- Garrison Kielor.
ALGOL by default means Algol 60 (68 was impressive but not widely used).
The Algol 60 Report does not contain the triliteral 'tag', and the only
instance of 'memory' is in the line "Dedicated to the memory of William
Turanski". AFAICS & AFAIR, the Report does not in any way deal with
layout in computer memory.
I used Algol 60, and have no recollection of any such thing being in the
ICL/ICT implementation.
The Report can easily be located on the Web by searching for that
dedication.
--
(c) John Stockton, nr London UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> RAH Prins : c.l.p.b mFAQ;
<URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.
Wayne, That's understandable.
Some day, if we are lucky, you may be old enough
to join our old-timers' club. <g> Rgds, JohnH
I was indeed looking at the Algol 68 spec. I have no idea how widely 68 was
used (or not) but it clearly was a progression in language features and
clearly influenced the subsequent design of Pascal and other languages.
Thanks for the clarification.
Wayne, That's understandable.
Some day, if we are lucky, you may be old enough
to join our old-timers' club. <g> Rgds, JohnH
Wait for me, ok? <g>
>Wayne Niddery (TeamB) wrote:
>
>> > Not at all. No way. They were designed by Wirth to allow a record to
>> > have different contents, depending on a switch value, the case
>> > selector (or tag). The case selector in original Pascal was always
>> > an existing field, not some pseudo one like "case Boolean of" or
>> > "case Byte of".
>>
>> Wrong - and clearly not supported by the link you provide
>
>Wayne, that may be, in that standard, it was not true in Wirth's
>Pascal. Not that it is crucial to what I wrote. It was meant as one
>piece of evidence.
>
Does quoting from my copy of Pascal User Manual and Report Second
Edition Copyright 1974 ISBN 0-387-90144-2 Page 45 count?
Assuming it does, the selector tag does not require an existing field,
although Wirth says it *usually* has one. But it was never required.
His example, from the same page is:
type maritalstatus = (married, wodowed, divorced, single)
type person =
record <attributes common to all persons>
case maritalstatus of
married : etc etc etc
Oz
--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
> Does quoting from my copy of Pascal User Manual and Report Second
> Edition Copyright 1974 ISBN 0-387-90144-2 Page 45 count?
Not sure, since it is the second edition. <g>
> Assuming it does, the selector tag does not require an existing field,
> although Wirth says it usually has one. But it was never required.
>
> His example, from the same page is:
> type maritalstatus = (married, wodowed, divorced, single)
> type person =
> record <attributes common to all persons>
> case maritalstatus of
> married : etc etc etc
Correct. But the versions of Pascal Wirth wrote for other systems than
his own hardware did require the tag was a field. IOW, it was slightly
limited compared to his original Pascal.
Anyway, this does not answer WHY Wirth introduced variant records. No
doubt it was also to save space (otherwise all different fields, active
or not, would have to be consecutive in memory), but I very much doubt
it was designed to perform the casting trick, e.g. to pass in a Real
and get out an Integer.
Does the Pascal described in your user manual have things like casts,
sizeof, or even bitwise operators?
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Hell is paved with good samaritans." -- William M. Holden
So what you are saying is Wirth is not allowed to change his own language in
order to improve it.
Silly.
> Anyway, this does not answer WHY Wirth introduced variant records. No
> doubt it was also to save space (otherwise all different fields, active
> or not, would have to be consecutive in memory), but I very much doubt
> it was designed to perform the casting trick, e.g. to pass in a Real
> and get out an Integer.
I've told you several times why there is the idea of variant records - the
same reason there is unions in C, Renames in COBOL, and so on. The reason is
to allow modelling of data so that records of different types can be read
sequentially from source (such as tape which was rather common at the time)
and be able to read those records with one record definition (EDI being the
repeated example). Without being able to do this, it would complicate data
storage and the reading and writing of that data. Variants make it much
easier, efficient, and flexible.
If you haven't seen examples of EDI before, here's one:
http://portlandgeneral.com/contact/ess_edi_samples.asp?bhcp=1
You will see that variants/unions/renames allow modelling of this pattern
perfectly, a header with some consistently defined fields (i.e. fixed length
definitions), followed by varying defintions depending on the record type.
These can also be nested to essentially any depth.
Once again I've *never* insisted that casting was the main reason, I've gone
out of my way to emphasize that it is a *consequent* ability that can be
taken advantage of - but one that Wirth could not have been ignorant of.
Is it really impossible for you to accept that, just maybe, others might
actually know more than you on some subjects?
Uh, this is Rudy you're talking about. <g,d & r>
For what it's worth, I agree with you Wayne. The concept was around long
before Pascal was born. Therefore, the benefits were already recognized
even though the reason(s) for implementing variants might have been
different.
Woody (TMW)
> So what you are saying is Wirth is not allowed to change his own
> language in order to improve it.
No, I am not. But I was talking about Wirth's original, which was
created earlier than the second edition.
> Silly.
The use of a strawman is silly, indeed.
> I've told you several times why there is the idea of variant records
> - the same reason there is unions in C, Renames in COBOL, and so on.
> The reason is to allow modelling of data so that records of different
> types can be read sequentially from source (such as tape which was
> rather common at the time) and be able to read those records with one
> record definition (EDI being the repeated example).
Exactly: ONE RECORD DEFINITION FOR DIFFERENT DATA --> polymorphism.
Without being
> able to do this, it would complicate data storage and the reading and
> writing of that data. Variants make it much easier, efficient, and
> flexible.
Fine, but that is not what you said before. Note that this (sub-)thread
was about the use of absolute, casting and other tricks to reach the
same (put type A in and read type B out). You claimed the main reason
for variants was the casting trick. I contested that, and still do.
I am not doing anything else. I actually said that the main reason for
variant records was a crude kind of ploymorphism, exactly as you
described above.
So guess I can assume you agree with me now?
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Blessed is the man, who having nothing to say, abstains from
giving wordy evidence of the fact."
-- George Eliot (1819-1880)
> Is it really impossible for you to accept that, just maybe, others
> might actually know more than you on some subjects?
Stop the tripe, please.
Wayne, you are actually making the points I have constantly made. IOW,
you are actually saying what I have said all the time.
But apparently you forgot that YOU claimed that the main reason for
variant recoerds was the kind of trick people use if they write in one
type and read out another. I have contested that, and have actually
constantly claimed what you are claiming now.
So what you say now is very acceptable. I have been saying it all the
time. I only found what you originally claimed (I'll gladly quote it
once again, if required) unacceptable.
FWIW, note that nothing in the standard or in Wirth's original says
that variant parts must overlap. It can be assumed that variant parts
do, but there is still nothing in the standard which makes parts
overlap perfectly, which would be the requirement for your casting
trick (and that is what you claimed).
Also note that what you put in and what you get out is dependent on the
system, on the format of both types, on endianness, etc. so this
casting trick CAN'T have been the main reason for variant records in a
language to be ported to various, very different systems. The crude
polymorphism (different types used as one single type), as you
described, is exactly the reason why variant records exist, as I have
always claimed, from the beginning on.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"The trouble with the Internet is that it's replacing
masturbation as a leisure activity." -- Patrick Murray.
Rudy, either you need to learn to read better or you need a new memory
because you cannot remember what's said in a thread. I agreed with you *very
early on* in this thread that *data-wise*, yes, this was a form of
polymorphism. The entire thread is here, it is easy to check.
It is you that continued to claim that there was no requirement for the
variants to overlay each other and could be sequential instead, but that is
ridiculous given the purpose of variants (i.e. your above polymorphism) -
without each variant reliably overlaying the others, this technique *CANNOT
WORK*. I.e, each variant begins at the same address, and because of a major
purpose for them - external storage and retrieval - they *should* always be
packed (because some *other* process in some *other* language on some
*other* computer could have produced that external storage and packed
records are one way to *help* ensure (not guarantee) compatibility).
> Fine, but that is not what you said before.
What in hell are you talking about, I've been repeating this same thing
through the entire thread. Would you like me to count the times I've used
the example term "EDI" in this thread??
> You claimed the main reason
> for variants was the casting trick. I contested that, and still do.
Again the entire thread is here to check Rudy, how many times do I have to
refute that - I NEVER said it was the MAIN reason, not even once. Since
I've had to repeat this so many times and you still insist on claiming
otherwise, at this point I have to call you an outright liar Rudy, but I can
only wonder at your possible motivation for continually misrepresenting my
statements like this.
> Rudy, either you need to learn to read better or you need a new
> memory because you cannot remember what's said in a thread. I agreed
> with you *very early on* in this thread that *data-wise*, yes
Fact is that I said:
<<
No, but they should IMO not be used to cast one type to another, unless
you really want to play dirty. That is not what they were meant for.
IMO, that is "clever coding".
>>
And you replied:
<<
That's exactly what they were designed for!
>>
That is what I have constantly been contesting. No more.
Once again: I have merely said they were not designed for this, IMO
rather dubious, trick.
Of course they were designed to save memory, although this could have
been done with separate record types as well. It was done to have
various different memory layouts as ONE type.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"My occupation now, I suppose, is jail inmate."
-- Unibomber Theodore Kaczynski, when asked in court what his
current profession was
You've earned it.
> But apparently you forgot that YOU claimed that the main reason for
> variant recoerds was the kind of trick people use if they write in one
> type and read out another.
The closest I ever came to that is one single sentence in an early (my 3rd I
think) post in this thread:
"That's *exactly* what they were designed for!"
The very most you can claim with this statement is that perhaps I
overemphasized the importance of that use. But nowhere does that statement
say anything like "main" or "most important". Indeed my very next statement
clearly indicated a very important purpose was for things like EDI (my first
mention of that use in the very same post, imagine that!).
The reason I made that statement was because I consider it a perfectly valid
use and not a "dirty hack" as you believe. That level of disagreement
between us is perfectly fine and it could have stopped there, but you went
on and made the ludicrous claim that the variant parts did not even have to
overlap, asserting that in attempt to discredit the use of variants for
casting, apparently not realizing, or forgetting, that overlaying the same
space was required for the other important use of which we apparently
agree - multiple overlapping record definitions such as EDI.
I've spent the rest of the thread trying to show you that they were very
much intended to overlay each other, that this was to be assumed in the spec
precisely because of its purpose, such purpose having ample precedent
already in other languages. You've spent the rest of it claiming I'm wrong
and continuing to wrongly assert that I said casting was the main (i.e.
*more important*) purpose.
> FWIW, note that nothing in the standard or in Wirth's original says
> that variant parts must overlap. It can be assumed that variant parts
> do, but there is still nothing in the standard which makes parts
> overlap perfectly, which would be the requirement for your casting
> trick (and that is what you claimed).
You still apparently don't get it: the overlapping is required for your
"poor-man's polymorphism too (the "poor-man" part being completely without
any basis BTW) - as I've shown, and as I've also said a couple of times now,
that the casting feature is a *consequent* of that requirement. There was no
reason for overlaying to be explicitly specified as such because at that
time, that was assumed, the use of such a construction was known with lots
of precedent and lots of actual use in other languages.
> Also note that what you put in and what you get out is dependent on the
> system, on the format of both types, on endianness, etc. so this
> casting trick CAN'T have been the main reason for variant records in a
> language to be ported to various, very different systems.
You are crossing the two uses without any basis. I've never suggested the
casting ability would be used for input or output of data that had to be
processed by other apps or systems, nor would I think to suggest such a
thing. That you think I would not be aware of the inherent problems of doing
that...!!!
But your assertion that the variants do not have to overlap would have the
same inherent problems - data would prove to be unusable by other systems
because programmers for those would be left guessing how the Pascal program
actually wrote the data. The Pascal program would also not be able to read
anything from other systems or languages. It is for this reason all cases of
a variants *must* overlap from the same starting address, and further that
any programmer that knew what he was doing would also define it as a packed
record so that others trying to process the same data could depend on the
supplied data definition and that each defined field directly followed the
last (it *must not* have unaccounted spacing applied implicitly by a
compiler).
> > But apparently you forgot that YOU claimed that the main reason for
> > variant recoerds was the kind of trick people use if they write in
> > one type and read out another.
>
> The closest I ever came to that is one single sentence in an early
> (my 3rd I think) post in this thread:
>
> "That's exactly what they were designed for!"
Indeed.
That is what I contested, and it is the only thing I have been
discussing in this entire thread, despite your many diversions. And it
is not true.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"You cannot depend on your eyes when your imagination is out
of focus." -- Mark Twain
And once again you omit the rest, including your other assertions (far from
the above being the *only* thing you've contested) and try to argue your
original accusation, which has no merit.
I'm done, I'm sure we've either entertained and/or bored eveyone else
thoroughly by now, so you may have the last word if you like.
See my other post.
> Of course they were designed to save memory,
No Rudy, that was not the reason and in fact it makes no sense whatever.
Since a variant can only hold one record definition at a time, how exactly
can it save memory? If that was the purpose it would fail completely as
there would be no difference and no advantage of using a variant definition
over using separate record definitions. The *definitions* don't take any
space!
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fm6et196y6m...@rvelthuis.de...
> >
> > And you replied:
> >
> > <<
> > That's exactly what they were designed for!
> > > >
>
> See my other post.
>
> > Of course they were designed to save memory,
>
> No Rudy, that was not the reason and in fact it makes no sense
> whatever. Since a variant can only hold one record definition at a
> time, how exactly can it save memory?
There are two ways to have various items in one record. One could do
this sequentially:
type
objekt = record
x, y : real;
area : real;
shape : (triangle, rectangle, circle);
{ fields for triangle }
side : real;
inclination, angle1, angle2 : angle;
{ fields for rectangle }
side1, side2 : real;
skew : angle;
{ fields for circle }
diameter : real;
end;
This is not very memory efficient, since you will never be accessing
diameter, side1, side2 or skew when shape is a triangle, anyway, or the
fields for triangle if the shape is a circle, etc. That is why you
could use variant records as a memory efficient variation on the above.
In both cases (variant record or not), you would have only one type for
various shapes, as desired, but the above would not be very memory
efficient.
If it didn't matter that you only had ONE type, you could just as well
do:
type
triangle = record
x, y : real;
area : real;
side : real;
inclination, angle1, angle2 : angle;
end;
rectangle = record
x, y : real;
area : real;
side1, side2 : real;
skew : angle;
end;
circle = record
x, y : real;
area : real;
diameter : real;
end;
This is in fact similar to the polymorphic approach you would choose
for objects with inheritence (x, y and area would be in the base class,
the other would be diifferent classes seriving from this).
When there were no classes yet, the variant record was the next best
thing. It combined the three records triangle, rectangle and circle in
one type. Of course, for memory efficiency, the type was as if the
three records overlapped.
But there was no requirement that if you wrote to diameter, you could
read from inclination, even if in most cases you probably could. They
were two distinguished values, belonging to a different set of fields,
and should simply not be confused.
Actually, the standard says that when one variant part is active, one
should not access fields of the other.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Why yes -- a bulletproof vest."
-- James Rodges, murderer, on his final request before the
firing squad.
> "That's exactly what they were designed for!"
>
> The very most you can claim with this statement is that perhaps I
> overemphasized the importance of that use. But nowhere does that
> statement say anything like "main" or "most important"
If you say something is EXACTLY DESIGNED for a certain purpose, I
assume one could say that you consider that purpose the main/most
important reason for its existence, don't you think?
Well, I have constantly been contesting that, and nothing else.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"If it wasn't for muscle spasms, I wouldn't get any exercise at
all."
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fm6gu099qmi...@rvelthuis.de...
> >
> > That is what I contested, and it is the only thing I have been
> > discussing in this entire thread, despite your many diversions. And
> > it is not true.
>
>
> And once again you omit the rest
Yes, because I was not discussing the rest. I was merely discussing the
casting trick (in the light of absolute doing something similar), and
said variant records were not designed for that purpose.
I can't help it that you sung entire operas trying to convince me of I
don't know what. I was only interested in contesting what you said, the
line I quoted. No more.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"I agree with the reforms, but I want nothing to change"
-- Ion Luca Caragiale, Romanian playwriter, 1880
Why would you ever do that? In my 25 years of professional programming I've
never seen a single example of someone doing this, they would be defined as
separate records *or* they would be defined as *variants*. This is a
strawman argument you are putting up, it is not at all realistic. Perhaps
some complete novice somewhere has thought the above to be a reasonable
idea but that would be it.
> type
> triangle = record
> rectangle = record
> circle = record
> This is in fact similar to the polymorphic approach you would choose
> for objects with inheritence (x, y and area would be in the base class,
> the other would be diifferent classes seriving from this).
This does not do *at all* what a variant does. To use separate records, one
has to know *before reading the record* which type of record structure to
read it into. That is the whole point if using variants - being able to read
records without knowing which *variant* of that record is being read and
being able to check afterwords.
> and in this case that would mean, for example, making good
> use of C unions!
I doubt that, as Pascal (and Algol which it was influenced by) were
defined/published before C was.
--
Anders Isaksson, Sweden
BlockCAD: http://web.telia.com/~u16122508/proglego.htm
Gallery: http://web.telia.com/~u16122508/gallery/index.htm
> Is it really impossible for you to accept that, just maybe, others
> might actually know more than you on some subjects?
Of course it is impossible! At least, it has never happened, yet.
> And you were there? <g>
Giggle this and giggle that! How many years have you be reading this
newgroup, and still missed the fact that some people actually *were*
there, at the time. Wayne is definitely one of them.
I used Pascal at University from c:a 1974(5?) (I began 1973 and we used
Algol and FORTRAN during the first year), and later we started playing
with unix and C. Pascal was still the main language during all my
studies. I'll have to dig out my old copy of the 'User Manual and
Report' (second edition, I think) and see what Wirth actually wrote.
> Wayne Niddery (TeamB) wrote:
>
> > and in this case that would mean, for example, making good
> > use of C unions!
>
> I doubt that, as Pascal (and Algol which it was influenced by) were
> defined/published before C was.
Hmmm... "K&R C" was published in 1978, but C was being developed from
1969 on, especially 1972 being a very productive year. Could well be
that Wirth had heard about it and its features before the publication.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Peace is constructed, not fought for." -- Brent Davis
> Rudy Velthuis [TeamB] wrote:
>
> > And you were there? <g>
>
> Giggle this and giggle that!
That was a <grin>.
> How many years have you be reading this
> newgroup, and still missed the fact that some people actually were
> there, at the time. Wayne is definitely one of them.
I doubt it. I mean, in 1974, I was already somewhere, at the time. And
Wayne is a few years older than I am, so he must have been somewhere,
too. But I doubt he was in Zürich.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"We need either less corruption or more chance to participate
in it."
> > type
> > objekt = record
> > x, y : real;
> > area : real;
> > shape : (triangle, rectangle, circle);
> > { fields for triangle }
> > side : real;
> > inclination, angle1, angle2 : angle;
> > { fields for rectangle }
> > side1, side2 : real;
> > skew : angle;
> > { fields for circle }
> > diameter : real;
> > end;
> >
> > This is not very memory efficient,
>
> Why would you ever do that? In my 25 years of professional
> programming I've never seen a single example of someone doing this
You ain't seen nothin' yet. The Windows API has a few such structures.
Anyway, I didn't say I would ever do that. But lacking variant records,
that would be the only alternative, right?
--
Rudy Velthuis [TeamB] http://www.teamb.com
"What a cruel thing is war: to separate and destroy families and
friends, and mar the purest joys and happiness God has granted us
in this world; to fill our hearts with hatred instead of love for
our neighbors, and to devastate the fair face of this beautiful
world." -- Robert E. Lee, letter to his wife, 1864
> Wayne Niddery (TeamB) wrote:
>
> > Is it really impossible for you to accept that, just maybe, others
> > might actually know more than you on some subjects?
>
> Of course it is impossible! At least, it has never happened, yet.
That is pure nonsense. I am very well aware of the fact that many
people know nmore about subjects than i do. But if I am aware of it, I
won't challenge them on what they say about such subjects.
Wayne said that variant records were specifically designed for the
casting trick. I have only been contesting that, since I am sure that
Wayne is wrong there, and, apparently does not know enough about the
subject.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Elegance is not a dispensable luxury but a factor that decides
between success and failure." -- Edsger Dijkstra
> Rudy Velthuis [TeamB] wrote:
>
> > And you were there? <g>
>
> Giggle this and giggle that! How many years have you be reading this
> newgroup, and still missed the fact that some people actually were
> there, at the time. Wayne is definitely one of them.
FWIW, Wayne said, elsewhere, that he has been a professional programmer
for 25 years now. That means he started in 1983, or late 1982. I assume
he was not "there", in Zürich, in 1974.
And, face it, the fact that he may have already studied programming at
that time doesn't mean he is right or knows better what Wirth did or
wanted. The same applies to you.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"God is love, but get it in writing." -- Gypsy Rose Lee.
If you have read this thread you will see that C is only *one* other
language to have an implementation of this kind of feature. COBOL, from
1960, had it, as well as other languages. I'm quite aware that C was
officially published after Pascal, but C was *also* influenced by Algol and
it is not a stretch to imagine that Wirth, Kernighan and Ritchie were all
well aware of each other's work as well as work done by their predecessors
and peers in *many* other languages. This kind of feature - overlaid record
definitions - was a very well known *and already used* feature by the time C
was published.
Correct - I've been *paid* for my programming work since early 1983.
However, I first learned to program, using Fortran, in 1971. I was taught
some computer history *as it was taught in 1971*. I have real (i.e. paid)
experience in both COBOL and IBM360/370 Assembler and from that experience
know about the use of overlaid record definitions in *actual applications*
(the reason I keep mentioning EDI as an example) and that such use was
already well established and in use long before I showed up. I had already
studied C and knew about unions, and so from both study and actual work
experience, when I subsequently learned Pascal, I immediately understood
variants *and why they existed*.
> And, face it, the fact that he may have already studied programming at
> that time doesn't mean he is right or knows better what Wirth did or
> wanted. The same applies to you.
Doesn't mean I know everything, of course! I know this particular subject.
Your assertions about variants, particularly about them not needing to
overlay, are absurd on the face of it. If you wish to continue deluding
yourself in believing you somehow know better than me or others in this
matter, there's nothing I can do to stop you, but deluded you will be.
Coming up with nonsensical arguments or examples to try to prove me wrong on
this particular subject only makes you look more silly.
> Anyway, this does not answer WHY Wirth introduced variant records. No
> doubt it was also to save space (otherwise all different fields, active
> or not, would have to be consecutive in memory), but I very much doubt
> it was designed to perform the casting trick, e.g. to pass in a Real
> and get out an Integer.
I would guess that you're right about variant records not being designed
in order to perform the "casting trick" on a *single* field.
So WHY have variant records?
Because Pascal was following the existing languages in how they overlaid
data variables (eg Fortran "common", COBOL "redefine") and read/wrote data
files.
So WHY would those languages do that?
Because memory (both disk and RAM) was so *incredibly* expensive that you
had to squeeze a complete accounting system onto a computer with only
32-KILObytes of RAM and 2 x 330-KILObyte floppy disks. And onto that
you've got to squeeze not only ALL your company's accounting data but ALL
the programs and ALL the Operating System - and ALL your disk buffers.
(For those interested in comparing the relative size/performance/cost of
hardware and software - such a mini-computer would set you back approx
$15K in mid-70's non-inflation-adjusted USD - about 6 times a graduate's
starting salary)
Disk buffers are expensive in terms of your limited RAM so you want to
minimise the number of files you have open - but opening+closing a data
file is expensive in time.
Solution: Store all your data in a minimum number of physical data files,
each with fixed length records (and if you don't want to cripple the disk
access speed you'll make sure that you use the disk's native record size)
And then you pack several smaller logical records into the one 512-byte
physical record.
So the same data buffer can contain very different logical data (Index,
Customer, Invoice, Cash, ...) depending from which portion of the data
file it was read - and *that* is the reason why you need different views
of the same disk buffer.
Because a common programming error was to access the data using a "wrong"
overlay field, ISTR that the TAG was introduced to allow a run-time
consistency check that the logical field name you were using actually did
correspond to the data in the physical disk buffer.
But the TAG had to be optional...
1) Size: While 1 byte in 512 might not be too bad, 1 byte in each of 16
32-byte logical records would be crippling.
2) Interoperability with other DP languages which didn't write such tags
3) Other cases when *you* didn't want a tag: In DIBOL/COBOL (although not
Pascal) *output* was also done by sending a complete line-record to the
printer. If you declared one single 132-byte print record and successively
redefined it with the fields for *all* the different types of output line
- headers, data, totals, etc, etc. - it both saved RAM space and, IME,
made it much, much easier to produce a nicely-lined-up report than writing
each individual field (a la Pascal).
--
Paul Scott
Information Management Systems
Macclesfield, UK.
Since you won't let this go, neither can I because I will not let you
continue to misrepresent (read LIE) about my statements without challenge.
If you want to continue making a battle and a spectacle out of this, in your
futile attempt to discredit me, so be it. By your misrepresentation of my
statements you have made this personal - and that unfortunately seems to be
you modus operandi in a lot of cases on these forums (not just with me).
I have more than made clear about my statements including the very post
where I initially made that statement you keep going back to. Therefore, if
you were genuinely *only* interested in correcting that, this thread
would've been long over. You insist on putting words in my mouth I never
spoke and *are not implied by my actual statement*. "...specifically
designed for the casting trick." is a perfect case in point. This amounts
to a LIE Rudy because my statement said no such thing - your wording implies
"only" or at least "most important". Actual meaning of my words, taken with
any reasonableness, only necessarily means *also*, and merely reflects my
judgement that such use is a valid use *in addition* to other purposes it
was designed for. I believe your English skills are far too good for you to
*accidently* misinterpret my statement and then refuse to accept any
correction.
As long as you keep insisting you know better what I meant, and actually
said, than I do; as long as you keep adding your words and meaning to my
statement, I will continue correcting you publicly.
I have repeatedly indicated that this casting ability was a *consequent*
feature of the fact that variant cases *must* be overlaid, yet you continue
to, not only ignore that, but then try to argue that I'm also wrong on the
requirement of overlaid variant cases in a vain attempt to prove me wrong on
the now relatively minor point about casting - and repeatedly ignoring that
such a claim by you, if true, would make the entire reason for variant
definitions useless for *any* purpose. You then compound that *further* by
trying to invent even more absurd claims for the purpose of variants to try
to prove they don't need to be overlaid. Do you really think such arguments
will discredit *me*??
If all you were genuinely trying to do is argue over whether the "casting
trick" is a valid use or whether or not Wirth expected or condoned such use,
there would be no reason for you to come up with these other arguments. The
only possible purpose of doing so cannot be to win an argument on merit, but
to discredit me at any cost - you wish to "prove" me wrong even when I'm
right.
Your subsequent denial that you are arguing these other points and that you
are *only* arguing the "casting trick" is even more ridiculous given the
current length of this thread and all the other arguments you have made
within it that I have properly rebutted.
No, *separate records* would be the only *reasonable* alternative.
As for the Windows API, I've certainly seen many cases where a structure
contains various fields that may or may not be in use depending on other
fields in that structure, and there are many cases of nested structures, but
even there I cannot think of anything I've seen where there are literally
complete "substructures" chained one after another in one large single
structure in this fashion. You'll need to point out an example of that. In
the case of nested structures, it is usally (if not always) a *pointer* to
that nested structure, so that if not present, only the size of a pointer is
"wasted".
Even with Fortran being the first language I learned, I could not remember
whether it too had this feature - never got to the point of actually using
it in my studies. I assumed it must but was not going to take the time to
look it up at this point, I felt I had already established enough precedent.
Thanks for commenting.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fm6zyj9zp2w...@rvelthuis.de...
> >
> > Anyway, I didn't say I would ever do that. But lacking variant
> > records, that would be the only alternative, right?
>
> No, *separate records* would be the only reasonable alternative.
Not if you wanted to have all the fields in one single type. You can't
have that with separate records.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Ever stop to think, and forget to start again?"
-- bumper sticker
> I subsequently learned Pascal, I immediately understood variants *and
> why they existed*.
Fine. Apparently that didn't stop you from making the statement you
made.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"I once heard two ladies going on and on about the pains of
childbirth and how men don't seem to know what real pain is. I
asked if either of them ever got themselves caught in a zipper."
-- Emo Philips.
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fm703q9zwkk...@rvelthuis.de...
> >
> > Wayne said that variant records were specifically designed for the
> > casting trick. I have only been contesting that, since I am sure
> > that Wayne is wrong there, and, apparently does not know enough
> > about the subject.
>
> Since you won't let this go, neither can I because I will not let you
> continue to misrepresent (read LIE) about my statements without
> challenge.
Wayne, I am not lying.
Read Message-ID: <47a2...@newsgroups.borland.com> to see what you
wrote.
You said there: "That's *exactly* what they were designed for!". So you
effectively said that the main purpose of variant records was the
casting trick.
You most definitely, undeniably claimed that, and I have not
misrepresented that, nor have I lied.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Nine out of ten doctors agree that one out of ten doctors is
an idiot."
> On Thu, 07 Feb 2008 11:48:05 -0000, Rudy Velthuis [TeamB]
> <newsg...@rvelthuis.de> wrote:
>
> > Anyway, this does not answer WHY Wirth introduced variant records.
> > No doubt it was also to save space (otherwise all different fields,
> > active or not, would have to be consecutive in memory), but I very
> > much doubt it was designed to perform the casting trick, e.g. to
> > pass in a Real and get out an Integer.
>
> I would guess that you're right about variant records not being
> designed in order to perform the "casting trick" on a single field.
>
> So WHY have variant records?
>
> Because Pascal was following the existing languages in how they
> overlaid data variables (eg Fortran "common", COBOL "redefine") and
> read/wrote data files.
No doubt.
>
> So WHY would those languages do that?
>
> Because memory (both disk and RAM) was so incredibly expensive
I know. I think I said it was to save memory. If variant records hadn't
existed, all fields of the different variants of the type would have to
be in memory sequentially, which would have wasted many precious bytes.
> But the TAG had to be optional...
> 1) Size: While 1 byte in 512 might not be too bad, 1 byte in each of
> 16 32-byte logical records would be crippling.
IOW, to save memory.
> 2) Interoperability with other DP languages which didn't write such
> tags
I'm not so sure about the interoperability issue. I don't think Wirth
had that in mind. He didn't implement other items required for that,
like bitwise operators, typecasts and sizeof().
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Raymond's Law of Software: Given a sufficiently large number of
eyeballs, all bugs are shallow." -- Eric S. Raymond
And what purpose would that serve?
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fm76aia8acv...@rvelthuis.de...
> >
> > Not if you wanted to have all the fields in one single type. You
> > can't have that with separate records.
>
>
> And what purpose would that serve?
I already said that: a crude form of polymorphism. The shape example
should be clear enough. This way you can have circles, triangles and
rectangles, in fact different types, but with a common base, and all
graphic objects, in one array, or as one type of parameter.
procedure moveobjekt(var obj: objekt; xmove, ymove: real);
begin
obj.x := obj.x + xmove;
obj.y := obj.y + ymove;
end;
...
for i := 1 to 100 do
moveobjekt(myarray[i], newx, newy);
Can't do that with different types. You also can't put different types
in an array, but you can put different objekts into an array. You can
also do that if they are not implemented as variant record (i.e. all
fields are simply layed out sequentially, as in my previous example),
but that would pretty much be a waste of space, and space was precious,
these days.
FWIW, the different shapes example, which I took from the standard, is
the classical example for the use of polymorphism. Today, we would use
a base class (shape) and subclasses (triangle, rectangle, circle) to
achieve the same.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"A committee is a group of people who individually can do nothing
but together can decide that nothing can be done." -- Fred Allen.
I've quoted myself already, I'm not denying this statement. It is your
interpretation that is wrong.
> So you
> effectively said that the main purpose of variant records was the
> casting trick.
I effectively said no such thing. Like I said, as long as you keep insisting
on this, I will continue to correct you. If you want to keep this thread the
main focus of your life for the next 10 years, I will continue to correct
you. Nothing in my words above indicates "main" no matter how much you wish
it to be true or how much you repeat it like a chant. Continuing to tell me
what I meant despite all clarification and demonstration to the contrary is
rather stupid.
One more time: I consider the "casting trick" to be valid *as a result of*
the nature of the variant structure, specifically the fact that the variant
cases are designed to overlay one another. That does not mean I think the
"casting trick" was the "only" purpose, or even the "most important" or
"main purpose", but only that it could not and would not have been
unexpected even by Wirth, and *has been used by many people for many years*
(de facto acceptance of that use) due to the nature of variants (and unions
and other language implementations of the same concept).
If you want to argue that Wirth never intended that use, that is an argument
*neither* of us can win since neither of us *knows* what Wirth actually
thought of of it, good or bad. But to suggest he would not have at least
been aware of it (as if casting was an unknown thing then) is silly, and
that he, AFAIK, never said anything against it means it is just as wrong for
you to claim he didn't allow or condone such a use as it would be for me to
claim that he did (and I have not made that claim).
The optional feature of having a tag indicate which variant was "active" is
also no defense, especially given that Wirth is the one that *made it
optional* in subsequent update of the language, and given that all one has
to do is set the switch - which is perfectly legal under *any* reading of
his specifications, in order to view the data under a different variant
case.
If you want to continue arguing this then I'll throw more gas on the fire
for you right here:
What it comes down to is that, using the variant structure, what you are
calling "polymorphism" of the data (which I don't disagree with as a
conceptual description) *is casting* in fact - the difference is that it is
a whole record being cast into different views, based on a tag value or some
other means, rather than casting individual fields. *The same data* is being
view differently via different data definitions - that is a definition of
(non-coercive) casting. There is ZERO difference in principle. I've always
understood that and is also a reason for the wording of my original
statement since I see them as parallel, though not identical, conceptually.
You obviously don't agree with this, but that does not make me wrong, it
only shows you can't see or do not agree with that parallel. That much is
your right of course, but it is not your right to make up phony assertions
to bolster your argument or to attempt to discredit me. If you want to
disregard the fact that I have actually used, and seen used, such features
throughout my career and learned about them much earlier again, you can do
so, but that only discredits you.
Which is of course, one of the reasons for coming up with *both* the idea of
variant records and polymorphic OO classes. Since both have existed in
various languages for many years (a version of variants dating all the way
back to Fortran, considered the first high-level language in the '50s), your
example is artificial. *Redefinition of the same memory space* is such a
*basic, obvious* solution that it begs the question of why you would imagine
people *not* using it or, even more fantastic, language designers not
thinking of it.
Using the "what if" scenario here is no more credible than "what if no one
ever thought of using variables".
> > You said there: "That's exactly what they were designed for!".
>
> I've quoted myself already, I'm not denying this statement. It is
> your interpretation that is wrong.
>
> > So you
> > effectively said that the main purpose of variant records was the
> > casting trick.
>
> I effectively said no such thing.
Sorry, but that is nonsense. If you say it is exactly what they were
designed for, then you most definitely say it is the main purpose of
their existence.
Sheesh!
You can jump around that a little longer, and write the next novel, but
that is what you said. You can hardly accuse me of lying if I
"interpret" it like that.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Humor is also a way of saying something serious."
-- T. S. Eliot (1888 - 1965)
> "Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
> news:xn0fm77uhaae7t...@rvelthuis.de...
> > >
> > > And what purpose would that serve?
> >
> > I already said that: a crude form of polymorphism. The shape example
> > should be clear enough. This way you can have circles, triangles and
> > rectangles, in fact different types, but with a common base, and all
> > graphic objects, in one array, or as one type of parameter.
>
> Which is of course, one of the reasons for coming up with both the
> idea of variant records and polymorphic OO classes.
Actually, if polymorphic OO classes had already existed, variant
records might never have come to life.
--
Rudy Velthuis [TeamB] http://www.teamb.com
"Few things are harder to put up with than a good example."
- Mark Twain (1835-1910)