Tag Archives: loops

Rich loops just got richer

The only missing piece in rich loops was building continuation nested loops — here the old C-like loops were obviously winning. In order to move closer to the podium I made few improvements, the first one — I cannot decide if this is an ugly hack or well designed concept.

I introduced iterator providers. Iterator provider is an object which can provide an iterator (yes, a groundbreaking approach). Usually you can think of a sequence as an iterator provider but there is another one obvious candidate — an iterator itself. It just returns copy of this. Such addition allows loops to work with iterators directly:

let iter = some_coll.getIterator();
for elem in iter do
  •••  
end

The second improvement is allowing to iterate over non existing data — in rigid mathematical sense an empty set is a not equal to no set, however so far I don’t see any danger with treating them here the same:

let none ?[Int] = null;
for elem in none do
  •••  
end

The third improvement is the smallest, it just supports method chaining. Advancing iterator instead of returning true/false returns an optional iterator. On a successful iteration — the iterator itself, on a failure — null. This part will be changed as soon as I implement reference passing as it was done in Smalltalk.

Those three changes combined let you write nested loops without any effort:

let coll = [1,2,3];
top: for x in coll do
  for y in top.iterator do
    System.Terminal.stdOut.writeLine(x,",",y);  
  end
end

It will write such pairs — (1,1), (1,2), (1,3), (2,2), (2,3), (3,3). Please note there are pairs where y is equal to x. When this is undesired start nested loop from the next element in collection — i.e. advance the iterator.

let coll = [1,2,3];
top: for x in coll do
  for y in top.iterator!next() do
    System.Terminal.stdOut.writeLine(x,",",y);  
  end
end

You should see — (1,2), (1,3), (2,3).

The iterator attribute of the top control is a copy of an iterator used internally by compiler, so you can alter it any way you want, it won’t harm the outer or inner loop.

Except for optimizing the internal wiring of rich loops I am done here, the plan is 100% completed.

Tagged

foreach can be the answer

C# foreach loop is undoubtedly elegant, however in daily use it is not efficient or versatile — I don’t envy the developers using the languages which dropped indexed for loop without solid substitution. When you need an index — usually you have to zip your collection with a range. Testing first or last element — a bit less common scenario — you need to add an extra scope with appropriate variables by hand. And adding nested continuation loop… — this is why I am glad C# still supports C-loop.

In Skila though, I am close to cover all the cases in a right way and have good reason not to introduce the old way of iterating. The performance is intact and you have concise syntax, starting from the basic form:

for elem in collection do
  ...
end

With just a control label (for any kind of loop — for, while and repeat-until) you can solve the common tasks:

loop: for elem in collection do
  stdOut.writeLine(loop.isLast); // `for` only
  stdOut.writeLine(loop.isFirst);
  stdOut.writeLine(loop.index);
  break loop; // here label is optional
end

All three “members” are just plain variables — when not used by the user, they are scrapped from the code, when used — they don’t leak. Nested loops are less of the rush (besides, they require more internal rewiring) so I’ll add them sometime in the future.

Tagged , ,

Loop controls: break and continue

My experience is no proof, but I didn’t see any real need of goto so far. That is in languages which have proper break and continue. Thus Skila does not have goto, but have rich break and continue. Don’t mind the syntax, I am not sure about it:

label ext_loop
while true do
  repeat
    break ext_loop;
  until false;
  continue;
end;

In this dummy example program immediately jumps out of those two loops, once it hits first break.

Note: you can label only loops.

Tagged

Loops: while and repeat-until

while loop works exactly like its counterpart in C# or C++, and repeat-until is analogous to do-while in those languages (or simply repeat-until in Pascal) with one exception. It always annoyed me that the latter loop does not create full scope, so I have to write such dreadful code as this:

{
  var loop_cond = false;
  do
  {
    loop_cond = ...
  }
  while (loop_cond);
}

The extra scope prevents leaking of control variable. In Skila repeat-until creates scope that ends after loop, so you can introduce variable inside loop and still use it in loop condition:

repeat
  var loop_cond = false;
  loop_cond = ...
until not loop_cond;

Note the lack of parentheses around loop condition. I have customized my keyboard layout but still typing no character is faster than typing single one.

Tagged