Thread overview
Lexical Closures and D
Feb 25, 2003
Walter
Feb 25, 2003
Dan Liebgold
Feb 25, 2003
Dan Liebgold
Feb 25, 2003
Dan Liebgold
Feb 26, 2003
Patrick Down
Feb 26, 2003
Patrick Down
Feb 26, 2003
Walter
Mar 09, 2003
Antti Sykari
February 25, 2003
The exciting thing about nested functions, delegates, closures, literals, etc. in D is that as I was implementing them and exchanging ideas about how to do it with Burton, I got the feeling that I was *discovering* something that was already in D. The reason is they fit so seamlessly into both the syntax and semantics already existing. Class member delegates and nested function delegates turned out to be the same thing! It's really fun when that happens.

Anyhow, I want to write an article about it, but I need a seminal example that's short, sweet, and captures the essence of this style of programming. Anyone have any ideas?


February 25, 2003
Ack... I think I might have misled you.  I've done some looking around for good descriptions of the types of closures, and it seems lexical closures are the real closures, and dynamic closures are the D (and old Lisp) style closures. It relates to the scope of the variables in the frame of the function definition... whether they will have lexical or dynamic scope.

Dynamic scope refers essentially to stack-based locals, or locals with dynamic extent (they leave scope when the execution thread exits their containing block).  Lexical scope is when variables' extents are dicated by the structure of the source.. that is if I call function A, A should get the scope of its definition as written in the source (d*mn the implementation).

Check out http://www.dreamsongs.com/NewFiles/HOPL2-Uncut.pdf to see a history of the transition from dynamic scope/closure to lexical scope/closure in Lisp. It appears that at this point even the term "dynamic scope" is long dead in that community.

Hopefully I'm not confusing things further...

In article <b3gn23$1e86$1@digitaldaemon.com>, Walter says...
>
>The exciting thing about nested functions, delegates, closures, literals, etc. in D is that as I was implementing them and exchanging ideas about how to do it with Burton, I got the feeling that I was *discovering* something that was already in D. The reason is they fit so seamlessly into both the syntax and semantics already existing. Class member delegates and nested function delegates turned out to be the same thing! It's really fun when that happens.
>
>Anyhow, I want to write an article about it, but I need a seminal example that's short, sweet, and captures the essence of this style of programming. Anyone have any ideas?
>
>


February 25, 2003

Ack, I may have misled you... in my search for info on closures, I've discovered that lexical closure generally refers to "real" closures, and the D style closures are generally called dynamic closures.

Dynamic closures mean the "captured" variables have dynamic scope, which means they are valid only as long as the execution thread is in their code block or subblock.

Lexical closures means that variables are captures according to lexical scoping, which means the scope is dictated by the structure of the source code. So if you call function A -- even if its from another scope through a delegate -- A must be able to access its environment as it exists in A's definition, let the implementation be d*mned.

For a perspective on the transition from dynamic to lexical scoping/closure, see http://www.dreamsongs.com/NewFiles/HOPL2-Uncut.pdf.  It seems that in the Lisp community, dynamic closure is a dead idea.

Hopefully I haven't confused things further...



February 25, 2003
Sorry for the double post.

In article <b3gsnm$1icm$1@digitaldaemon.com>, Dan Liebgold says...
>
>
>
>Ack, I may have misled you... in my search for info on closures, I've discovered that lexical closure generally refers to "real" closures, and the D style closures are generally called dynamic closures.
>
>Dynamic closures mean the "captured" variables have dynamic scope, which means they are valid only as long as the execution thread is in their code block or subblock.
>
>Lexical closures means that variables are captures according to lexical scoping, which means the scope is dictated by the structure of the source code. So if you call function A -- even if its from another scope through a delegate -- A must be able to access its environment as it exists in A's definition, let the implementation be d*mned.
>
>For a perspective on the transition from dynamic to lexical scoping/closure, see http://www.dreamsongs.com/NewFiles/HOPL2-Uncut.pdf.  It seems that in the Lisp community, dynamic closure is a dead idea.
>
>Hopefully I haven't confused things further...
>
>
>


February 26, 2003
"Walter" <walter@digitalmars.com> wrote in news:b3gn23$1e86$1@digitaldaemon.com:
> Anyhow, I want to write an article about it, but I need a seminal example that's short, sweet, and captures the essence of this style of programming. Anyone have any ideas?


Not a great example but here's wordcount recast.
BTW, http://www.digitalmars.com/d/index.html
doesn't compile.

import file;
import ctype;

void withWordsFromFile(char[] file, void delegate(char[]) callback)
{
  char[] input;
  bit inword;
  int wstart;

  input = cast(char[])file.read();

  for (int j = 0; j < input.length; j++)
  {
    if (isalpha(input[j]))
    {
      if (!inword)
      {
          wstart = j;
          inword = 1;
      }
    }
    else if (inword)
    {
      callback(input[wstart .. j]);

      inword = false;
    }
  }

  if (inword)
  {
    callback(input[wstart .. input.length]);
  }
}

int main (char[][] args)
{
    int w_total;
    int[char[]] dictionary;

    for (int i = 1; i < args.length; ++i)
    {
      try
      {
        int w_cnt;

        void wordHandler(char[] word)
        {
          dictionary[word]++;
          w_cnt++;
        }

        withWordsFromFile(args[i],&wordHandler);

        printf("%.*s : %d words\n", args[i], w_cnt);
        w_total += w_cnt;
      }
      catch(FileError e)
      {
        printf("%.*s\n",e.toString());
      }
    }

    if (args.length > 2)
    {
      printf("%d words total", w_total);
    }

    printf("--------------------------------------\n");
    char[][] keys = dictionary.keys;
    for (int i = 0; i < keys.length; i++)
    {
      char[] word;

      word = keys[i];
      printf("%3d %.*s\n", dictionary[word], word);
    }
    return 0;
}


February 26, 2003
In article <b3gn23$1e86$1@digitaldaemon.com>, Walter says...

>Anyhow, I want to write an article about it, but I need a seminal example that's short, sweet, and captures the essence of this style of programming. Anyone have any ideas?

A sorting example.  Not really what you are looking for either and it does not access local scoped variables. But perhaps it will sparks some ideas.

template SortTemplate(Type)
{
void insertionSort(Type array[], bit delegate(Type a,Type b) lessThan)
{
for (int i=1; i < array.length; i++)
{
Type index = array[i];
int j = i;
while ((j > 0) && lessThan(index,array[j-1]))
{
array[j] = array[j-1];
j = j - 1;
}
array[j] = index;
}
}
}


class Person
{
this(char[] n, int a)
{
name = n;
age = a;
}

char[] name;
int    age;
}


alias instance SortTemplate(Person).insertionSort PersonSort;


void PrintByName(Person[] people)
{
PersonSort(people,
delegate bit(Person a, Person b) { return a.name < b.name; } );

printf("\nPeople by sorted by name\n========================\n");
for(int i = 0; i < people.length; ++i)
printf("%.*s,%d\n",people[i].name,people[i].age);
}


void PrintByAge(Person[] people)
{
PersonSort(people,
delegate bit(Person a, Person b) { return a.age < b.age; } );

printf("\nPeople by sorted by age\n========================\n");
for(int i = 0; i < people.length; ++i)
printf("%.*s,%d\n",people[i].name,people[i].age);
}



void main(char[][] argv)
{
Person people[];

// Naughty
people ~= new Person("Zeb",27);
people ~= new Person("Betty",22);
people ~= new Person("Casy",15);
people ~= new Person("Mike",50);
people ~= new Person("Linda",12);
people ~= new Person("Freda",33);
people ~= new Person("Rudy",45);
people ~= new Person("Holly",18);

PrintByName(people);
PrintByAge(people);
}



February 26, 2003
Yes, a sort might do the trick. In my own work, I've had to use globals and semaphores to pass context info to the qsort sorting function. Ugh. Nested functions will work much better.

"Patrick Down" <Patrick_member@pathlink.com> wrote in message news:b3j6je$19a$1@digitaldaemon.com...
> In article <b3gn23$1e86$1@digitaldaemon.com>, Walter says...
>
> >Anyhow, I want to write an article about it, but I need a seminal example that's short, sweet, and captures the essence of this style of
programming.
> >Anyone have any ideas?
>
> A sorting example.  Not really what you are looking for either and it does
not
> access local scoped variables. But perhaps it will sparks some ideas.
>
> template SortTemplate(Type)
> {
> void insertionSort(Type array[], bit delegate(Type a,Type b) lessThan)
> {
> for (int i=1; i < array.length; i++)
> {
> Type index = array[i];
> int j = i;
> while ((j > 0) && lessThan(index,array[j-1]))
> {
> array[j] = array[j-1];
> j = j - 1;
> }
> array[j] = index;
> }
> }
> }
>
>
> class Person
> {
> this(char[] n, int a)
> {
> name = n;
> age = a;
> }
>
> char[] name;
> int    age;
> }
>
>
> alias instance SortTemplate(Person).insertionSort PersonSort;
>
>
> void PrintByName(Person[] people)
> {
> PersonSort(people,
> delegate bit(Person a, Person b) { return a.name < b.name; } );
>
> printf("\nPeople by sorted by name\n========================\n");
> for(int i = 0; i < people.length; ++i)
> printf("%.*s,%d\n",people[i].name,people[i].age);
> }
>
>
> void PrintByAge(Person[] people)
> {
> PersonSort(people,
> delegate bit(Person a, Person b) { return a.age < b.age; } );
>
> printf("\nPeople by sorted by age\n========================\n");
> for(int i = 0; i < people.length; ++i)
> printf("%.*s,%d\n",people[i].name,people[i].age);
> }
>
>
>
> void main(char[][] argv)
> {
> Person people[];
>
> // Naughty
> people ~= new Person("Zeb",27);
> people ~= new Person("Betty",22);
> people ~= new Person("Casy",15);
> people ~= new Person("Mike",50);
> people ~= new Person("Linda",12);
> people ~= new Person("Freda",33);
> people ~= new Person("Rudy",45);
> people ~= new Person("Holly",18);
>
> PrintByName(people);
> PrintByAge(people);
> }
>
>
>


March 09, 2003
"Walter" <walter@digitalmars.com> writes:

> The exciting thing about nested functions, delegates, closures, literals, etc. in D is that as I was implementing them and exchanging ideas about how to do it with Burton, I got the feeling that I was *discovering* something that was already in D. The reason is they fit so seamlessly into both the syntax and semantics already existing. Class member delegates and nested function delegates turned out to be the same thing! It's really fun when that happens.
>
> Anyhow, I want to write an article about it, but I need a seminal example that's short, sweet, and captures the essence of this style of programming. Anyone have any ideas?

Touching the topic of closures...

There's currently a discussion about "Closures vs. objects" at comp.lang.lisp that I found quite interesting:

http://groups.google.com/groups?selm=ccc7084.0303042203.f057f86%40posting.google.com

-Antti