← Back to context

Comment by weinzierl

2 years ago

I think it is fair to say that integral types are pretty common in software across the board. Pascal declared integral types like this:

  month: 1..12;

You could also use this nomenclature for characters:

  letter: 'A'..'Z';

When I first learned C, I could not believe that it did not support that. I wouldn't not have dreamed that almost half a century later I still don't have this feature back.

To be clear:

- Many things have improved and I'm glad I don't have to write my software in Pascal[1] today.

- I don't really miss the generalization of this feature. Things like refinement types would be nice, but what Pascal provides would be enough to make life so much better.

It also works for arrays, by the way, which very elegantly sidesteps the 0-based/1-based controversy.

  FooPerMonth: array[1..12] of Foo;

  LandingsPerRouletteWheelPos: array[0..36] of Landings;

[1] The old one, I don't know much about Delphi and later developments.

Take a look at Ada sometime, it really takes that to eleven.

   type Digit is range 0 .. 9;

   type Unsigned_Byte is mod 2 ** 8;

   type Binary_Floating_Point is digits 15 range -1.0 .. 1.0;

   type Binary_Fixed_Point is delta 2.0 ** (-32) * Pi range (-Pi / 2.0) .. (Pi / 2.0); 

   type Decimal_Fixed_Point is delta 0.01 digits 5;

  • Conspicuously missing are Ada's arrays, which I feel properly take Pascal's to 11 due to the fact that describing their index bounds need not also prescribe that arrays statically allocate that much storage, as in `type Unsigned_Byte_Array is array (Positive range <>) of Unsigned_Byte`, where `subtype Positive is Integer range 1 .. Integer'Last`. Substitute `Positive` with `Natural` where you like.

Yes, this was a really nice advantage Pascal had that I'm amazed hasn't been picked up by things like C#. It's not just zero or one based.

(It's been long enough I'm not completely sure of the syntax) Time : Array [2000..2100, 1..12, 1..31] of OneDayInfo;

Avoid allocating the 2000 years in the past while allowing directly indexing with the year field.

And you could use enum types as array indexes. In C# you're always casting them to int whenever an enum is an array index and every cast is a case where the compiler won't have your back in hunting for errors.

And it did *not* use duck typing.

Month: 1..12 DaysOfChristmas: 1..12

You couldn't assign which day of Christmas to a month.

The stricter the compiler the fewer bugs will even compile and the faster you'll find the problem.

As for his color assignment issue--you still need to be able to set it to "purple", but representing it his way pushes this back to whatever routine parsed the configuration. There's only one place that needs to make the check and anything bogus will be caught during startup.

One really nice thing about object pascal(and nim I think) is that you can declare enums as array indexes.

  type
    TMonth = (mJan = 1, etc);

    TFooPerMonth = array[TMonth] of integer;

  • That is a great feature.

    You can have those semantics in .net, because any hashable can be a dictionary key. It will have a small performance penalty, which won't matter in 99% of cases. You could roll your own collection and get O(1).

    F# lets enum values be records, which is the most elegant solution IMO for manageable counts and fields.

If I could just have an enum restricted to the enumerated values, I'd be happy. It's pure insanity that even a c++ enum class can take on an integer value.