Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do you manage without genetics?

16 views
Skip to first unread message

Anton

unread,
Nov 9, 2008, 8:12:47 AM11/9/08
to
Hello all!

I wanted to ask how people deal with one aspect in huge
applications written in Pascal. I mean the lack of generic
abstract data types, which allow to have the same fundamental
algorithm (say, a list, a tree, or a hashtable) to be
implemented once and used with different element types.

Even in OOP, it is a problem, unless the language provides a
special mechanism for generics (which C# 1.1 does not, for
example), because either such structure will be not type-safe
or it will have performance issues connected with (un)boxing.

I like Pascal and have to write in Pascal for the University,
so I'd really like to know how professional standard Pascal
programmers cope with this problem.

Thanks in advance,
Anton

winston19842005

unread,
Nov 9, 2008, 9:45:07 AM11/9/08
to
On 11/9/08 8:12 AM, in article
Xns9B51A4EC18E3A...@85.214.105.209, "Anton"
<anton.txt@g[oogle}mail.com> wrote:

I *think* we use Delphi - or a Pascal with such extensions.
In the old days, we rolled different procedures or functions for each data
type.

Marco van de Voort

unread,
Nov 9, 2008, 10:03:29 AM11/9/08
to
On 2008-11-09, Anton <anton.txt@g> wrote:
> I wanted to ask how people deal with one aspect in huge
> applications written in Pascal. I mean the lack of generic
> abstract data types, which allow to have the same fundamental
> algorithm (say, a list, a tree, or a hashtable) to be
> implemented once and used with different element types.

(mostly from Delphi/FPC experience)

You duplicate a bit of code or use a generator, if your compiler supports
inline, you can also make a few helper functions or a class wrapper that
only adds the proper casts, and are optimized away runtime.

In an OOP dialect, half of the time you need to do it once for some basic
ancestor anyway. It's not like that you duplicate it hundred fold (and even
then, a simple program that generates the code will be ten minutes)

In my last big project with lots of datatypes, the business objects were
generated from the RDBMS table definitions, so adding a bit of code to also
instantiate the typesafe container-wrapper for each types was no problem.

> I like Pascal and have to write in Pascal for the University,
> so I'd really like to know how professional standard Pascal
> programmers cope with this problem.

While generics are comfortable, specially for typesafe containers, it's more
a minor annoyance that is easily solved than a big problem. Typically with
bigger projects you invest big in the datastructure anyway, and the timeloss
of duplicating the code is peanuts. And while duplicating code or wrapper
code is generally frowned upon, it is not a life or death issue.

Anton

unread,
Nov 9, 2008, 1:07:17 PM11/9/08
to
Thanks for the reply, Marco!

> if your compiler supports inline, you can also make a few helper
> functions or a class wrapper that only adds the proper casts, and are
> optimized away runtime.

I am sorry, but I am not very fammiliar with neither inline
functions nor "wrappers" in OOP, so let me te write down how I
have understood you:

With wrappers, I just make a class that implements, say, a
collection of objects, which is of course un-typed. Then for
each of the element types I write a wrapper around the generic
class that will typecast elements back and forth when I put
them in and out of the collection.

With inline functions, well, I don't know how these can be
utilized at all ;) Inline or not, a function has specified
parameter types...

Anton

Marco van de Voort

unread,
Nov 9, 2008, 4:41:03 PM11/9/08
to
On 2008-11-09, Anton <anton.txt@g> wrote:
>> if your compiler supports inline, you can also make a few helper
>> functions or a class wrapper that only adds the proper casts, and are
>> optimized away runtime.
>
> I am sorry, but I am not very fammiliar with neither inline
> functions nor "wrappers" in OOP, so let me te write down how I
> have understood you:
>
> With wrappers, I just make a class that implements, say, a
> collection of objects, which is of course un-typed.

And then you either implement your type specific ones using inheritance or
encapsulation. Encapsulation is better for inlining afaik.

> Then for each of the element types I write a wrapper around the generic
> class that will typecast elements back and forth when I put them in and
> out of the collection.

Correct

> With inline functions, well, I don't know how these can be
> utilized at all ;) Inline or not, a function has specified
> parameter types...

function something:TChild; inline;

begin
result:=Tchild(ancestor_something);
end;

The function only changes type, but if they are both the same size (e.g.
like the pointer based classes in Delphi), it is a pure cast, and thus
effectively a no-op when inlined.

CBFalconer

unread,
Nov 9, 2008, 5:32:46 PM11/9/08
to

It is quite simple. maxint describes the maximum available
integer, for any use. -maxint describes a minimum value. If you
want any smaller range you just define a suitable type:

CONST
MAXVALUE = 1000;
MINVALUE = -100;

TYPE
myinteger = MINVALUE .. MAXVALUE;

and now you can define components of type myinteger. It is up to
the compiler to take advantage of any savings in code or storage
space made possible by this.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

Chris Burrows

unread,
Nov 9, 2008, 8:49:32 PM11/9/08
to
"Anton" <anton.txt@g[oogle}mail.com> wrote in message
news:Xns9B51A4EC18E3A...@85.214.105.209...

> I wanted to ask how people deal with one aspect in huge
> applications written in Pascal. I mean the lack of generic
> abstract data types, which allow to have the same fundamental
> algorithm (say, a list, a tree, or a hashtable) to be
> implemented once and used with different element types.
>

In ISO Standard Pascal one technique to handle this sort of task (albeit in
a significantly less general way that you can do with 'Generics') is to
represent a known set of varying data types using 'variant records' and to
use 'procedure variables' to control any variation of runtime behaviour that
might be required.

>
> I like Pascal and have to write in Pascal for the University,
> so I'd really like to know how professional standard Pascal
> programmers cope with this problem.
>

Unless you are intending to restrict yourself to ISO Standard Pascal I
recommend that you ask your question again in a newgroup that is more
appropriate for the paticular dialect of Pascal that you are using (e.g. GNU
Pascal, FreePascal, Delphi etc.). That dialect is very likely to have
non-standard extensions that can be used as an alternative to Generics. If
you happen to be using the latest version of Delphi then Generics are
directly supported anyway so the same question in a Delphi newsgroup may
well be redundant.

--
Chris Burrows
Armaide: Oberon-07 ARM Development System for Windows
http://www.armaide.com


Anton

unread,
Nov 10, 2008, 4:34:39 AM11/10/08
to
Chris Burrows:

> In ISO Standard Pascal one technique to handle this sort of task
> (albeit in a significantly less general way that you can do with
> 'Generics') is to represent a known set of varying data types using
> 'variant records' and to use 'procedure variables' to control any
> variation of runtime behaviour that might be required.

And another problem with this approach is the size of the
resulting variant record which is the maximum size of the
types it 'includes'.

> Unless you are intending to restrict yourself to ISO Standard Pascal...

Unfortunately the only version of Dephi I can use at Uni is
7... But I'll take that into account for the programming that
I do on my own.

And I came to this newsgroup because it's my personal interest
to use Standard Pascal. Even if it is Delphi, unless, of
course, sticking to it does not make programming significally
slower. Not that I am stubborn or something...

Anton

Anton

unread,
Nov 10, 2008, 4:39:27 AM11/10/08
to
Thanks for help Marco, but... I still don't quite understand how
you intend inline functions to be used.

How is such an inline function supposed to enforce type
safety? Can't one just bypass it and send any object to my
collection?

Did you mean inlining the methods of the Wrapper Class, and
only the typecasting operation?

Anton

Marco van de Voort

unread,
Nov 10, 2008, 8:04:54 AM11/10/08
to

Yes, so inlining just decreases the runtime cost of the wrapping (to zero in
some cases even), and doesn't add to the typesafety itself.

Anton

unread,
Nov 10, 2008, 3:12:25 PM11/10/08
to
Thank you, Marco, Winston and Chris!

Chris Burrows

unread,
Nov 10, 2008, 4:26:49 PM11/10/08
to
"Anton" <anton.txt@g[oogle}mail.com> wrote in message
news:Xns9B527FF0A4FA8...@85.214.105.209...

>
> And another problem with this approach is the size of the
> resulting variant record which is the maximum size of the
> types it 'includes'.
>

True in some circumstances but not all. Highly unlikely in the case where
you were attempting to use variant records implement generic algorithms. For
further information:

a) Check the definition of NEW in the Pascal Standard (NOT in the Delphi
reference manual!)

b) Note that on many systems pointer variables are the same size no matter
what datatype they point to.

FYI, since Pascal, Wirth eliminated problems associated with variant records
by introducing the much safer 'type extension' concept. See his 1987 paper
'Extension of Record Types' published in Vol 19 of the ACM SIGCSE Bulletin:

http://portal.acm.org/citation.cfm?id=24728.24729

CBFalconer

unread,
Nov 10, 2008, 5:58:48 PM11/10/08
to
Chris Burrows wrote:
>
... snip ...

>
> Unless you are intending to restrict yourself to ISO Standard
> Pascal I recommend that you ask your question again in a newgroup
> that is more appropriate for the paticular dialect of Pascal that
> you are using (e.g. GNU Pascal, FreePascal, Delphi etc.). That
> dialect is very likely to have non-standard extensions that can
> be used as an alternative to Generics. If you happen to be using
> the latest version of Delphi then Generics are directly supported
> anyway so the same question in a Delphi newsgroup may well be
> redundant.

Bear in mind that the Borland related versions, such as Turbo and
Delphi, DO NOT implement Pascal. They omit some of the most
important features of standard Pascal, and misapply many standard
procedures and functions. Especially noticeable are the absence of
f^, put, and get.

Some of this may be handled with txtfiles.zip, on my download page.

Anton

unread,
Nov 10, 2008, 6:16:20 PM11/10/08
to
Chris Burrows:

> a) Check the definition of NEW in the Pascal Standard (NOT in the
> Delphi reference manual!)

It was a surprize indeed :)

...
Hope you don't mind skimming throung the template unit below
and giving some feedback. Is it the way you meant using
variant records and function pointers?


unit PseudoGenerics;

interface

type
ColElements = (one, another);
CompareRes = (more, equal, less, typeErr);

oneColElem = record
{fields specific to this type}
end;

anotherColElem = record
{fields specific to this type}
end;

TColElement = record
case tp:ColElements of
one: (oneData :oneColelem);
another: (anotherData :anotherColElem);
end;

PSLNode = ^TSLNode;

TSLNode = record
el: TColElement;
next: PSLNode;
end;

TSortedList = record
tp: ColElements;
head: PSLNode;
end;

{Exporting this function}
function SLInsert(sl:TSortedList; el:TColElement): boolean;

implementation
type

ftCompareFunc = function(el1, el2: TColElement):CompareRes;
ftGetHashFunc = function(el:TColElement):integer;
{... + other functions...}

FuncSet = record
CompareFunc: ftCompareFunc;
GetHashFunc: ftGetHashFunc;
{and so on...}
end;
var
FuncTable: array[ColElements] of FuncSet;

function Compare(el1, el2: TColElement):CompareRes;
begin
if (el1.tp <> el2.tp) then begin
Compare := typeErr;
end else begin
Compare := FuncTable[el1.tp].CompareFunc(el1, el2);
end;
end;

{---- Type-specific functions ----}
function oneCompare(el1, el2: TColelement):CompareRes;
begin
{Implementations omitted}
end;
function anotherCompare(el1, el2: TColelement):CompareRes; begin
end;
function oneGetHashCode(el: TColelement):integer; begin end;
function anotherGetHashCode(el: TColelement):integer; begin end;
{---------------------------------}

{---- Functions for sortedList -------}
function SLInsert(sl:TSortedList; el:TColElement): boolean;
var
OK: boolean;
begin
OK := true;
if(el.tp <> sl.tp) then begin
{handle type error}
OK:=false;
end else begin
{Some code using the "generic" Compare function}
end;
end;
{-------------------------------------}

begin {Initialization}
with FuncTable[one] do begin
CompareFunc := oneCompare;
GetHashFunc := oneGetHashCode;
end;
with FuncTable[another] do begin
CompareFunc := anotherCompare;
GetHashFunc := anotherGetHashCode;
end;
end.

0 new messages