A r t i c l e s
Navigation

Note: This site is
a bit older, personal views
may have changed.

M a i n P a g e

D i r e c t o r y

Rare Case Dynamic Typing in Pascal


Dynamic typing is useful but it is also dangerous. In this article I will show you how to kind of escape the Pascal typing system when you really need to. Well not really escaping the typing system.. actually just making use of it!

This is not exactly implementing "dynamic typing" into Pascal - it is just a clever way of emulating dynamic typing without using Variants or Array Of Const.

Where I find dynamic typing powerful is when multiple types can be passed in to a procedure. This means no having to rewrite the procedure for each type. This also means no having to make an abstract class so that different classes can be passed in to the procedure to do different things (and maybe using RTTI).

There are cases where even Array of Const and Variants are not enough power when sending multiple types into a procedure or function. See the below program for why.

The below program allows one to pass literally ANY type into a procedure. The disadvantage of using this TMulti record to pass any type into a procedure is that the TMulti type requires a few more initiation steps. You must set the TMulti type to your desired type before passing into the procedure. Whereas in a dynamic typing language you do not have to set up your desired type.

However, in a strongly typed language, what did you expect? It's more verbose but more obvious that you are diddling around with changing types! It is not so obvious that you are diddling around with changing types in a dynamicly typed language - and sometimes this gets folks into deep trouble.


program Project1;
{$APPTYPE CONSOLE}


type
  // like a TVarRec but more powerful since it does not contain a PAnsiString
  // it contains a real ansistring. It also can contain a text file or
  // any other type which tvarrec does not allow
  TMulti = record
    mString: string;
    mFile: text;
    // insert more mOtherTypes... mInteger, mBoolean, etc. if you need them

    // we must know what type we are passing by using an enumeration
    mtType: (mtFile, mtString);
  end;


procedure multitest(s: string; var tm: TMulti);
begin

  { write text to a file }
  if tm.mtType = mtFile then
    writeln(tm.mFile, s);

  { write text to a string }
  if tm.mtType = mtString then
    tm.mString:= tm.mString + s;
end;
You could try to do the above with a TVarRec or array of const but it will not work so easily for you.. try and see.

With a TMulti you declare an actual ansistring, not a pointer. And you declare a text handle.. not a pointer. It is fine to do concatenating with the record field parameter being passed in, since it is a VAR parameter BY REFERENCE and not a BY VALUE parameter.

See other funny info on TVarRec/Array Of Const and vtString/vtAnsistring here: Usenet Post

Abstraction, Data Hiding

These tricks are really just about abstraction and data hiding. Instead of rewriting a procedure for each type, you make one procedure and do it all there.

Similar tricks can be seen when writing a "writeln driver". You could make a writeln driver so that instead of WriteLn writing to a text file on your hard drive, it writes to a string. The string would be your "text" handle itself. Again these are just abstraction tricks.

The freepascal sockets unit has functions that make sockets act as text handles too. Some people prefer not to abstract writeln, and some prefer that writeln not be a bird, airplane, or a pig. But it is a powerful technique nonetheless.


Now what do I mean about a bird, airplane, pig, or string? I'm talking about dynamic types.. types that can change. This is not always a good thing. Other times it is very powerful.
var
  string1: TMulti;
  file1: TMulti; // dynamic type: can be a file, string, bird, airplane
begin
  
  string1.mtType:= mtString;
  string1.mString:= 'yada yada ';
  
  // using the same procedure to write to multiple types! dynamic typing emulated
  multitest('testing123', string1);

  // write to a file (or a bird, or an airplane, or any other type)
  file1.mtType:= mtFile;
  assign(file1.mFile, 'testing.txt');
  rewrite(file1.mfile);

  // using the same procedure to write to multiple types! dynamic typing emulated
  multitest('testing abc', file1);
  close(file1.mFile);

  writeln('STRING 1: ', string1.mstring);
  readln;
end.
In the above program we use the same procedure to write text to multiple different types! We could have written to a pchar, string, file, or any other text related type. Even though a Text File is completely different beast than a string, they both hold text! What's in common? We want to write text somewhere - a text file being treated the same as a string type is very powerful.

In the above program we combine strong typing with dynamic typing. It takes a bit more work to create our dynamic type.. we have to initiate it:

  mt.mtType:= mtFile;
  mt.mtType:= mtBird; // ever hear the expression "it's a bird, no it's an airplane!"
  mt.mtType:= mtAirplane; // it can be any type!
  mt.mtType:= mtRacoon; // it can be any type
  mt.mtType:= mtHouse; // it can be any type
Sure, in a language with real dynamic typing you wouldn't have to initiate types:
 s = 'blah blah'; // string
 s = 4; // integer ... magic!

Safety Hazards

The above language.. allowing us to turn a type into an integer or a string on the fly, looks like magic.. but is the above really that great for software development? Is this magic essential?

That dynamic typing you see above, available in languages like PHP, has loads of problems too. When you WANT your integer to remain an integer, and it ends up being a string at the wrong time in the wrong place - you will cry.

Don't know what I mean?

Consider a shopping cart application built with PHP (PHP has dynamic/weak typing):

# Try this in PHP... pretend it was a late night coding and your currency
# looked okay

$dummy1 = '20usd';
#... ...
#... ..
#... ...
#.. ...
#... ... a few lines later, you type in what you THINK is right
$dummy2 = 'usd55';
print $dummy1 + $dummy2;

The output on my web browser after running this PHP script is:
20
This is dangerous! the output should be 0, but PHP tries to be smart and ends up being dangerous. Simple mistake by you late a night, you forget that your USD should be separate from your integer.

See also: Examples-Of-Strong-Typing-Advantages

Maybe through a concatenation or a customer error the USD was attached to the string. Yes it is a stupid mistake to mix USD in with the number.. but it happens.

STUPID MISTAKES HAPPEN OFTEN IN PROGRAMMING. A dollar sign $ gets thrown in accidentlly. This happens all the time. A USD or CDN gets thrown in to a type that is supposed to only contain numbers. Yes you can use IsNum() but it will slip through and you will forget.. many times. Even the most advanced and intelligent programmers create stupid mistakes in programs.

In a strongly typed language, a number is a number.. and a dollar sign would not be allowed. In a weakly typed and dynamically typed language like PHP... dollar signs will slip in without warning.

Our whole program is toast because of a typeless language! Weak/dynamic typing in php allows one to make any "invalid string" pass through the program as an "integer". Some strings get turned into bizarre integers.. such as 20USD turning into 20 while USD5 does not turn into 55.

It's $55.00 off and your customer is really confused. And your business loses money. NOT TO MENTION SECURITY VULNERABILITIES.

Dynamic Typing NOT Always Needed

This is why dynamic typing in my opinion should only be used sparingly! You can escape dynamic typing in strongly typed languages by using a TMulti type if a VarRec or a Variant isn't enough.

Don't be confused about why I called it TMulti - TMulti is just something I made up. You could call it anything. Many people don't realize that they can make their own TMulti style types up any time they like.

A TMulti (homebrewed) type allows you to make use of emulated dynamic typing. It just takes a bit more keyboard typing. But not really that much keyboard typing if you think about how often you really need this feature - not that much. Consider that in a dynamically/weakly typed language you would have to make work arounds every time you wanted your types to be strong and static!

TVarRec/Variant/Array Of Const

So go ahead and try building the above program using a TVarRec. You'll find out that there is no Text File type in the TVarRec, and that there is no Ansistring type in the TVarRec (rather a pointer to an ansistring). You can work around the Text File issue by using a PText (Text^) but that is a messy more dangerous pointer hack.

The TMulti program above successfully finds a way around the limitations of TVarRec. You make your own TVarRec-ish type called TMulti, but you just can't use as cleanly as an array of const offers. You can use an Array of TMulti if you need more than one item passed in to your function or procedure, but you won't be able to have the syntactic sugar of Array Of Const. If you don't know what I mean, simply try declaring an array of TMulti and compare to an Array of Const. A TMulti can't be like an array const because it is a record that you are passing in, not a compiler magic array of const.

But Are Records Inefficient?

One other disadvantage of using this Dynamic Typing work around in Pascal as described above, is that the TMulti record being passed in is extra overhead compared to passing in a single type such as a string or a file handle. But is it extra overhead compared to say making an abstract class and passing that in? Probably worrying about such things is premature optimization.

Is it extra overhead compared to if you were using a Dynamically typed language? Probably not since the dynamic language would be slow.. and dynamic languages some how have to figure out what types you were passing in at run time.

i.e. don't worry about premature optimization - if you need the power of dynamic typing badly enough that the extra overhead isn't an issue anyway - all we are doing is sending in a record with a few empty dummy types)


Note: when I say "dynamically/weakly" I do not mean that all weak typed languages are automatically dynamically typed ones. I'm just using PHP as our example in this article which is both dynamically and weakly typed. There are languages which are not both dynamically and weakly typed. For example, the C language is weakly typed but is not so dynamically typed.

For simplicity of this article I am comparing modern pascal to PHP.

About
This site is about programming and other things.
_ _ _