August 06, 2005
Before I start I better say it out load; I am a Pascal programmer.

I use Pascal because it helps me write correct code and allows me to write a buffer overflow vulnerability if I like. Much like D does, but D has a more modern touch to it that I start to like very much.

Anyway, two powerfull basic types in Pascal that I use all the time as they generate so nice compiler/runtime errors when debugging my applications, and in general gives more functionality with less code, are ranges and sets.

D already sort of have ranges in a pseudo form in slices. Sets is not present at all but are too usefull to be omiited :). I think it would be great to build upon. And I think the syntax would be natural.

I give some pseudo-code for how it could be implemented and what it can be good for. This code could be even more compact given the strength of ranges and sets, but I go for clarity :).


module foobar;

import std.stdio;

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
set Days { Day }
range WeekDay { MON..FR }

int main(char[][] args) {
// Let people be an associative array of Days, where each element
// represent the week days a person is available (as a set).
  Days[char[]] people;
  people["John"] = [MON..WED, FRI..SUN];
  people["Sally"] = [TUE, FRI..SAT];

// Let free be a Days set, and set all values.
  Days free = [Day];


// Iterate all persons and remove busy days from the free set.
  foreach (Days days; people) {
    free *= days;  // * is intersect, + is union and - is difference.
  }

// Prefer weekdays, remove days in weekend if any weekday is available
// A set is false if empty, and true if contains one or more values.
  if (free * [WeekDay]) {
    free *= WeekDays;
  }

// If the resulting set is empty to bad, else write out possible days.
  if (free == []) {
    writefln("No possible free days for all people.");
  } else {
    writef("Possible free days are:);
  // Foreach on a set should loop over all contained values
    foreach (Day day; allAvailable) {
      char[][Day.max] daynames = ["monday", "tuesday", "wednesday",
          "thursday", "friday", "saturday", "sunday"];
      writef(" " ~ daynames[day]);
    }
    writefln(".");
  }
}

The output of this program would naturaly be:
Possible free days are: tuesday friday.


For optimum usability range checks should be enforced on enums, ranges and sets. So that assigning for example 42 to the Day enum or adding 12 to the Days set would cause a range check error. Only problem here is backward compatibility (Especially old C code), so maybe "strict" (Or some other better suitable word) could be added as a keyword, example:
strict enum Foo { BAR, BAZ }
To indicate that an enum, range or set should be range checked?

For small sets (64 values or less with no spread) some operator overloading, a struct and typedefs could be used to simulate all this. But for larger sets (and better performance?) making it into the core of the language makes just as much sense as strings and complex numbers.

regards
	Fredrik Olsson
August 07, 2005
"Fredrik Olsson" <peylow@gmail.com> wrote in message news:dd35k1$21r3$1@digitaldaemon.com...
> Before I start I better say it out load; I am a Pascal programmer.
>
> I use Pascal because it helps me write correct code and allows me to write a buffer overflow vulnerability if I like. Much like D does, but D has a more modern touch to it that I start to like very much.
>
> Anyway, two powerfull basic types in Pascal that I use all the time as they generate so nice compiler/runtime errors when debugging my applications, and in general gives more functionality with less code, are ranges and sets.

I believe sets in Pascal are implemented as bit arrays (hence the
restrictions on the types to ordinal types). So with a slightly different
syntax you can probably get most of Pascal's sets with bit arrays. For
example a set of chars would be bit[char.max]. You'd have to write
union/intersection/etc specially but that doesn't seem hard.
For example
  enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
  typedef bit[Day.max] Days;
  Days schedule;
  schedule[Day.MON .. Day.THU] = true; // recall D slicing is not inclusive
  if (schedule[Day.FRI]) {...}