On Monday, 18 August 2014 at 07:44:14 UTC, Joakim wrote:
A technical report draft: http://acm.math.spbu.ru/~gassa/az/alphabet-city/technical-report.html

It would be good if you could expand on your thoughts on D from part 11 of your technical report and post it somewhere, so that others can learn from your experience.

Hmm, the program does contain a few features which are convenient or possible at all because of the choice of language. For example, I found inner functions and internal iteration (opApply and foreach body converted to a delegate) very useful when iterating over small changes on complex objects. Still, the examples are very solution-specific, so it would require a bit of thought to convert them to points of general interest.

I'll elaborate a bit. Suppose we have a large and complex object (a Scrabble game state), and we want to iterate over small changes to that object (single word plays). In pseudocode, that would be:

(1)
consider object o
for each change to object o:
    yield o

Here, "each change to object" actually spans a few hundred lines in a few inner recursive functions.

The yield must transfer control to another part of the code (also complex) which, for example, accounts for good states. There are many states generated, but only a few valid and good states get actually copied, so the yield must be by reference to avoid excessive copying. For example:

(2)
for each o yielded:
    if (o is valid and good):
        copy o to storage

Here, the checks for being valid and good, or maybe some other stuff, can also be long enough.

The catch is that the iteration on changes (which can be one of several possible iteration schemes) must be separated from the use of yielded states (which can again be one of several uses).

After a bit of attempting to simulate yield efficiently for my case, I realized that there is no need for the generator to actually hang in the heap waiting for another call. The desired flow of the program is non-concurrent: for each o yielded by (1), we process it in the body of (2) immediately and return control right after that.

The concept of delegates makes this possible: (2) can be made a delegate and passed as an argument to (1). Well, it can be emulated in other languages by passing an object containing the state, but the code would be harder to follow.

The mechanism for inner iteration makes it convenient: just write

foreach (o; call (1) as a function)
    put (2) as a body

and the body (2) is automatically converted into a delegate. This syntax coincides with my way of thinking about the problem, so I'm delighted to use it.

Ivan Kazmenko.

Reply via email to