43

Sometimes when I am programming, I find that some particular control structure would be very useful to me, but is not directly available in my programming language. I think my most common desire is something like a "split while" (I have no idea what to actually call this):

{
    foo();
} split_while( condition ) {
    bar();
}

The semantics of this code would be that foo() is always run, and then the condition is checked. If true, then bar() is run and we go back to the first block (thus running foo() again, etc). Thanks to a comment by reddit user zxqdms, I have learned that Donald E. Knuth writes about this structure in his paper "Structured programming with go to statements" (see page 279).

What alternative control structures do you think are a useful way of organizing computation?

My goal here is to give myself and others new ways of thinking about structuring code, in order to improve chunking and reasoning.

Note: I'm not asking about how to generalize all possible control structures, whether by using jne, if/goto, Lisp macros, continuations, monads, combinators, quarks, or whatever else. I'm asking what specializations are useful in describing code.

skaffman
  • 381,978
  • 94
  • 789
  • 754
A. Rex
  • 30,789
  • 21
  • 85
  • 95
  • Re: your example. If the `undo` parts are just intended as examples, then what you have there is not a very "alternative" control structure. It's called *exception handling* and has existed (although not necessarily under that name) for almost as long as programming itself. If you *do* intend the `undo` s to be part of the semantics, then it's a *transaction* and isn't very alternative, either. – Jörg W Mittag Nov 27 '10 at 22:34
  • Note to confused readers: I have edited my question to emphasize my question and de-emphasize particular examples. In particular, I removed one example which the preceding comment references. – A. Rex Nov 27 '10 at 23:39
  • 2
    Needs to be community wiki to avoid closing for subjectivity (no real answer). – Matchu Nov 27 '10 at 23:45
  • Big list, *"I find that ..."*, generally speculative 'cause the question is about control structures *not* implemented (or not widely known). This question doesn't really fall crashing to the ground anywhere in particular, but it is suspicious lots of different ways. And 5 hours in the answers are about ways to *avoid* needing new control structures or ways to build the example from existing ones...I'm going to go with NaRQ. – dmckee --- ex-moderator kitten Nov 28 '10 at 01:56
  • 2
    For the "split_while", in [Sather](http://www.icsi.berkeley.edu/~sather/Documentation/LanguageDescription/webmaker/DescriptionX2Eiterators-chapte-1.html) you can do `loop statement1; while!(condition); statement2; end;` – Jordão Nov 28 '10 at 04:10
  • 1
    FWIW such a control structure (`splitWhile`) can be implemented pretty easily in Scala: http://paste.pocoo.org/show/297023/ :-) – missingfaktor Nov 28 '10 at 04:16
  • 1
    Even easier in Clojure: https://gist.github.com/718750 :D – Rayne Nov 28 '10 at 09:06
  • 1
    I posted a similar question on Programmers.Se: http://programmers.stackexchange.com/q/22070/389 – Maniero Nov 28 '10 at 16:12
  • @bigown: Thanks. Hopefully that will generate some new answers, if the question is not reopened here. – A. Rex Nov 28 '10 at 18:01

28 Answers28

20

One that's fairly common is the infinite loop. I'd like to write it like this:

forever {
  // ...
}
Jordão
  • 51,321
  • 12
  • 105
  • 132
  • 17
    #define ever (;;) for ever {} – Jookia Nov 28 '10 at 02:21
  • 5
    @Jookia: `#define forever for(;;)` – Jordão Nov 28 '10 at 02:32
  • I'd prefer repeat over forever, but maybe they're separate concepts. – Peter Gibson Nov 28 '10 at 03:00
  • @Peter Gibson: normally you `repeat` something `until` some condition, like in [Pascal](http://www.freepascal.org/docs-html/ref/refsu51.html#x122-13200010.2.6). – Jordão Nov 28 '10 at 03:19
  • @Jordão: forever is a long time - repeat implies that you might break out at some point. It would be like repeat... until(false) - where you leave the until(false) bit out because it is ugly :) – Peter Gibson Nov 28 '10 at 03:29
  • Forever is the _intent_, but I agree; `repeat`, or even `loop`, would also work out. – Jordão Nov 28 '10 at 03:33
  • Scala: `def forever(f: => Unit) { while(true) f }`. – missingfaktor Nov 28 '10 at 04:12
  • @missingfaktor: I still want to be able to use `break` and `continue`. For your code, `break` turns to `return`; but `continue` is not addressed. – Jordão Nov 28 '10 at 04:18
  • 1
    @Jordão: Scala doesn't have either of these control constructs - `break`, and `continue`. It's a primarily a functional language, and imperative features though available are generally discouraged. Due to popular demand, they recently provided `break`(though in the form of a library method). We still don't have `continue` (and I don't think we'll ever have, as you hardly need to write your hand-rolled loops in a functional language.) – missingfaktor Nov 28 '10 at 04:30
  • @Jordão: and oh yes, you can use this library `break` in the `forever` control construct I defined in my second last comment above. – missingfaktor Nov 28 '10 at 04:34
  • 1
    `forever` is certainly a lot prettier than `while(true)`! – Sean Patrick Floyd Nov 29 '10 at 15:13
  • Microsoft's QBASIC had "Do...Loop", without conditions, which would run until an "Exit Do" was executed. VB.Net provides the same statement. Ironically, what I find myself wanting in VB is a control statement to express the intent "just do the following once" (sometimes to allow a break-out; more often to define a variable's scope). – supercat Dec 02 '10 at 18:41
  • @supercat: I've often used nested scopes in C# for that (but there's no break-out); but this is a general indication that you need to refactor some code to a new method. To do it once, you can use a `do { ... } while(false)` construct, but semantically, a `once { ... }` would be better. Maybe you can add this one to this question. I've also thought about the `never { ... }` (or `dont { ... }`) construct, as just a compiler backed way to comment-out some code. But I didn't think of many advantages to add it to this question. What do you think? – Jordão Dec 02 '10 at 20:38
  • 1
    @Jordão: I don't especially like "once" as a word, but I'm not sure what would be better. Maybe just "Block" for a word-paired language like VB, so it could be paired with "End Block". For C derivatives, one could use braces without any keyword if one doesn't need the jump-to-end semantics, though it may be nice to have some marker that the brace-pair exists for scoping (rather than to delimit an "if" that accidentally got deleted). – supercat Dec 02 '10 at 20:42
  • @supercat: makes sense, add it to this question then. – Jordão Dec 02 '10 at 20:55
20

Sometimes, I need to have a foreach loop with an index. It could be written like this:

foreach (index i) (var item in list) {
  // ...
}

(I'm not particularly fond of this syntax, but you get the idea)

Jordão
  • 51,321
  • 12
  • 105
  • 132
  • 10
    In python this is handled using the built in enumerate function which takes a list and returns a list of (index, item) pairs. "for i,item in enumerate(list)". – Peter Gibson Nov 28 '10 at 03:19
  • Definitely! I've often written a `foreach` loop, but then realized I need an index later. – A. Rex Nov 28 '10 at 03:20
  • 2
    In Ruby we use Array#each_with_index – Tianyi Cui Nov 28 '10 at 14:15
  • 1
    In Harbour you have `item:__enumIndex` to retrieve it. Also, you can use `item:__enumIsFirst` and `item:__enumIsLast` that return bool. Worth notice that Harbour also permits descending foreach, and foreach with multiple arrays at same time. Descending is very useful to delete items during the loop without sync issues. – Bacco Jan 07 '17 at 01:02
19

Most languages have built-in functions to cover the common cases, but "fencepost" loops are always a chore: loops where you want to do something on each iteration and also do something else between iterations. For example, joining strings with a separator:

string result = "";
for (int i = 0; i < items.Count; i++) {
    result += items[i];
    if (i < items.Count - 1) result += ", "; // This is gross.
    // What if I can't access items by index?
    // I have off-by-one errors *every* time I do this.
}

I know folds can cover this case, but sometimes you want something imperative. It would be cool if you could do:

string result = "";
foreach (var item in items) {
    result += item;
} between {
    result += ", ";
}
Nathan Baulch
  • 18,737
  • 4
  • 49
  • 52
munificent
  • 11,074
  • 2
  • 35
  • 51
  • I like it but would 'item' be in scope during the 'between' block, and if so, is it the previous or next item? If I wanted to turn something like ["a", "1", "b", "2"] into "a=1,b=2" then I need to alternate between "=" and ",". How would I get a loop index in the between block? Or do I need a non-local variable? – Andrew Dalke Nov 28 '10 at 09:31
  • That'd be nice. The `split_while` addresses this concern, though only for `while` and not the other common loops. – A. Rex Nov 28 '10 at 15:38
  • @Andrew, you could always provide both the previous and next items in the loop: `between(prev, next) {`. – munificent Nov 28 '10 at 18:10
  • 5
    In Haskell using "intersperse" that would not be a chore, imho. – LennyStackOverflow Nov 29 '10 at 21:43
  • @Andrew, that's the whole point of this. The `between` block would only be executed *between* two items, so not after the last. – munificent Dec 08 '10 at 04:13
  • @minificent: bah, that's what happens when I come back to an SO thread after months away. – Andrew Dalke Dec 08 '10 at 18:57
  • you should not be looping for this, but `join(array, ',')` – Chii Jan 20 '11 at 04:36
  • @Chii, What does `join` do in that example? – Ehtesh Choudhury Jun 06 '12 at 16:51
  • @Shurane: join in this example is meant to be the function which takes an array, and concatenates each element, separated by the 2nd argument (the `,` in this case). most languages have this built in, such as the javascript `Array.join`. – Chii Jun 07 '12 at 14:22
18

Loop with else:

while (condition) {
  // ...
}
else {
  // the else runs if the loop didn't run
}
Jordão
  • 51,321
  • 12
  • 105
  • 132
  • If the loop does run, foo wont be ran the first time it runs, only at the end. It's the opposite of what he described. – Rayne Nov 28 '10 at 09:08
  • 6
    Python has exactly this construction. Also, it allows to add 'else:' to 'for:' and 'try:'. – 9000 Nov 28 '10 at 11:10
  • 3
    In Python the else runs if the loop terminated "normally", either it executes without a break or never ran. – Brian Neal Nov 28 '10 at 15:27
  • +1, but for me it's mostly the wish for a for(){...} else {...} – tstenner Dec 08 '10 at 18:14
  • @tstenner: I include that in my question when I say "Loop" with else. It's just that I've provided a while loop example. But yes, the idea is to have any loop type with an else. – Jordão Dec 08 '10 at 18:24
13
{
    foo();
} split_while( condition ) {
    bar();
}

You can accomplish that pretty easily using a regular while:

while (true) {
    foo();
    if (!condition) break;
    bar();
}

I do that pretty frequently now that I got over my irrational distaste for break.

munificent
  • 11,074
  • 2
  • 35
  • 51
  • 6
    That's true, but I feel this doesn't address the question. I don't particularly care about *how* you choose to implement these alternative control structures, whether with `while` and `break` or (gasp!) even `goto`. I want ways of *thinking* about code. I have found that split_while lets me think about the structure in a new way, analogous to how `while` is a structural improvement over a conditional jump. – A. Rex Nov 27 '10 at 21:59
  • 6
    This doesn't answer the OP question. – Maniero Nov 27 '10 at 22:01
  • 4
    Ppl isn't reading the question. It's strange to see this "answer" top voted. – Maniero Nov 28 '10 at 11:36
  • 1
    Maybe the implicit point of this answer is that there is already enough control structures - why add more language support for them when you already have a good enough abstraction? – GreenieMeanie Dec 03 '10 at 18:12
13

If you look at Haskell, although there is special syntax for various control structures, control flow is often captured by types. The most common kind of such control types are Monads, Arrows and applicative functors. So if you want a special type of control flow, it's usually some kind of higher-order function and either you can write it yourself or find one in Haskells package database (Hackage) wich is quite big.

Such functions are usually in the Control namespace where you can find modules for parallel execution to errorhandling. Many of the control structures usually found in procedural languages have a function counterpart in Control.Monad, among these are loops and if statements. If-else is a keyworded expression in haskell, if without an else doesn't make sense in an expression, but perfect sense in a monad, so the if statements without an else is captured by the functions when and unless.

Another common case is doing list operation in a more general context. Functional languages are quite fond of fold, and the Specialized versions like map and filter. If you have a monad then there is a natural extension of fold to it. This is called foldM, and therefor there are also extensions of any specialized version of fold you can think of, like mapM and filterM.

HaskellElephant
  • 9,388
  • 4
  • 34
  • 66
11

This is just a general idea and syntax:

if (cond)
   //do something
else (cond)
   //do something
also (cond)
   //do something
else
   //do something
end

ALSO condition is always evaluated. ELSE works as usual.

It works for case too. Probably it is a good way to eliminate break statement:

case (exp)
   also (const)
      //do something
   else (const)
      //do something
   also (const)
      //do something
   else
      //do something
end

can be read as:

switch (exp)
   case (const)
      //do something
   case (const)
      //do something
      break
   case (const)
      //do something
   default
      //do something
end

I don't know if this is useful or simple to read but it's an example.

Maniero
  • 8,009
  • 6
  • 36
  • 74
10

With (lisp-style) macros, tail-calls, and continuations all of this is quaint.

With macros, if the standard control flow constructs are not sufficient for a given application, the programmer can write their own (and so much more). It would only require a simple macro to implement the constructs you gave as an example.

With tail-calls, one can factor out complex control flow patters (such as implementing a state machine) into functions.

Continuations are a powerful control flow primitive (try/catch are a restricted version of them). Combined with tail-calls and macros, complex control flow patterns (backtracking, parsing, etc.) become straight-forward. In addition, they are useful in web programming as with them you can invert the inversion of control; you can have a function that asks the user for some input, do some processing, asks the user for more input, etc.

To paraphrase the Scheme standard, instead of piling more features onto your language, you should seek to remove the limitations that make the other features appear necessary.

Brian
  • 1,812
  • 12
  • 9
  • 1
    I am actually pretty sure that macros + tail-calls + delimited continuations (+mutable state perhaps) indeed *are* the universal basis for all possible control structures. I think so because the Cont monad is the mother of everything :) – jkff Nov 27 '10 at 21:58
  • 6
    This still leaves open the question of *what* control structures you would implement. Okay great, Lisp macros generalizes all of the control structures I need; okay great, maybe they shouldn't be in the core language. This still doesn't answer *which* specializations I choose. We have historically found that `if` and `while` can be useful -- what else? – A. Rex Nov 27 '10 at 22:02
  • 5
    @A. Rex: actually, I can't remember the last time I used a `while` loop outside of some kind of *very special* context. I believe the last time was in a hand-written recursive descent parser, where I used it more as a DSL element than an actual loop. I usually use maps, folds, catamorphisms, filters, transformers. I don't even use plain iterators that often. In a modern language, pretty much the *only* reason to use a `while` loop is when you want an *infinite* loop such as in the event loop of an operating system. But for that, you might just as well use a tail recursive function. – Jörg W Mittag Nov 27 '10 at 22:23
  • 1
    Nitpick: there is a paper floating around which proves that exceptions can be more powerful than continuations. (In fact, one of the common criticisms against exceptions is that they are just `GOTO` under a different name.) So, technically speaking continuations are a restricted version of `try`/`catch`. But this is hairsplitting of the worst kind :-) I fully understand what you mean. It can be useful, though: the Volta CIL->ECMAScript compiler uses exceptions to implement continuations and threads, for example. – Jörg W Mittag Nov 27 '10 at 22:28
8

if not:

unless (condition) {
  // ...
}

while not:

until (condition) {
  // ...
}
Jordão
  • 51,321
  • 12
  • 105
  • 132
  • It took me a while to get used to them (in Perl), but I do feel like I use them natively now. – A. Rex Nov 28 '10 at 03:40
  • 1
    Scala: `def unless(cond: => Boolean)(f: => Unit) { if(!cond) f }` and `def until(cond: => Boolean)(f: => Unit) { while(!cond) f }`. :D – missingfaktor Nov 28 '10 at 04:37
  • I actually dislike them in Perl. I tried to use them, but found, that they obfuscate the code rather than make it clearer. Maybe it's because in other languages one usually doesn't use such constructs... – Inshallah Nov 30 '10 at 18:52
  • To clarify what I'm trying to say: in other languages one usually uses `if (!..)` and `while (!..)` instead, which makes them much more idomatic across languages. – Inshallah Nov 30 '10 at 19:37
  • I think these constructs can make the _intent_ clearer: compare, e.g., `while(!done)` to `until(done)`. – Jordão Nov 30 '10 at 19:59
  • @Jordão, it's a subtle issue - I have to look once at `if (!..)`, twice at `unless (..)`, and a thousand times at the rest. – Inshallah Nov 30 '10 at 20:52
8

Labeled loops are something I find myself missing sometimes from mainstream languages. e.g.,

int i, j;
for outer ( i = 0; i < M; ++i )
    for ( j = 0; j < N; ++j )
        if ( l1[ i ] == l2[ j ] )
           break outer;

Yes, I can usually simulate this with a goto, but an equivalent for continue would require you to move the increment to the end of loop body after the label, hurting the readability. You can also do this by setting a flag in the inner loop and checking it at each iteration of the outer loop, but it always looks clumsy.

(Bonus: I'd sometimes like to have a redo to go along with continue and break. It would return to the start of the loop without evaluating the increment.)

Boojum
  • 6,326
  • 1
  • 28
  • 32
  • You can also emulate multilevel break and continue with an exception. It isn't the most elegant of solutions. I did have to resort to it once. On the plus side, it does work even if the innermost loop has been extracted to another function. – Andrew Dalke Nov 28 '10 at 09:35
  • 1
    For the record, JavaScript and Java both have this. – Nicole Nov 30 '10 at 17:02
  • +1 for redo. I find myself wanting this, especially when traversing and inserting/erasing only some times in a list. (In c++ that is, dunno if it can be done well in other ) – Macke Dec 03 '10 at 21:22
8

I propose the "then" operator. It returns the left operand on the first iteration and the right operand on all other iterations:

var result = "";
foreach (var item in items) {
    result += "" then ", ";
    result += item;
}

in the first iteration it adds "" to the result in all others it adds ", ", so you get a string that contains each item separated by commas.

helium
  • 1,069
  • 8
  • 13
  • 2
    What about a having a new block allowed anywhere inside of a for loop... maybe having an else... `first { ... } else { result += ", "; }` – Nicole Nov 30 '10 at 16:59
8
if (cond)
   //do something
else (cond)
   //do something
else (cond)
   //do something
first
   //do something
then
   //do something
else (cond)
   //do something
else
   //do something
end

FIRST and THEN blocks runs if any of 3 conditionals are evaluated to true. FIRST block runs before the conditional block and THEN runs after the conditional block has ran.

ELSE conditional or final write following FIRST and THEN statement are independent from these blocks.

It can read as :

if (cond)
   first()
   //do something
   then()
else (cond)
   first()
   //do something
   then()
else (cond)
   first()
   //do something
   then()
else (cond)
   //do something
else
   //do something
end


function first()
   //do something
return
function then()
   //do something
return

These functions are just a form to read. They wouldn't create scope. It's more like a gosub/return from Basic.

Usefulness and readability as matter of discussion.

Maniero
  • 8,009
  • 6
  • 36
  • 74
6

How about

alternate {
    statement 1,
    statement 2,
    [statement 3,...]
}

for cycling through the available statements on each successive pass.

Edit: trivial examples

table_row_color = alternate(RED, GREEN, BLUE);

player_color = alternate(color_list); // cycles through list items

alternate(
    led_on(),
    led_off()
);

Edit 2: In the third example above the syntax is maybe a bit confusing as it looks like a function. In fact, only one statement is evaluated on each pass, not both. A better syntax might be something like

alternate {
    led_on();
}
then {
    led_off();
}

Or something to that effect. However I do like the idea that the result of which ever is called can be used if desired (as in the color examples).

Peter Gibson
  • 16,547
  • 5
  • 56
  • 57
  • That's interesting. Can you give me an example use case? – A. Rex Nov 28 '10 at 03:21
  • How is this a control construct? – missingfaktor Nov 28 '10 at 04:36
  • @missingfaktor: Because control changes after each time through "alternate()". If implemented as a function (in most languages) then led_on() and led_off() would be called before calling alternate. It could be emulated with lambdas and a non-local variable to hold state, but that's extra complication. On the other hand, this seems a rare need and not worth having specific syntax. After all, it's easy to implement something mostly like it in Python with itertools.cycle(). – Andrew Dalke Nov 28 '10 at 09:19
  • 1
    +1 for the thought. I think this might do what you suggest... def alternate(*args): while True: for arg in args: yield arg() itertools.cycle() is probably a library that does something similar, but this got me thinking more about generators and coroutines! Edit: formatting terrible – David Ackerman Nov 28 '10 at 09:29
  • You can accomplish this kind of thing using just functions with closures. In JavaScript for example, you could write this code: function cycle(choices) { var i = 0; return function() { var current = i; i = (i + 1) % choices.length; return choices[current]; }; } You could use this code like this: var colors = cycle(["blue", "white", "red"]); for (var i = 0; i < 5; ++i) alert(colors()); If you use Python, this function is already provided in itertools and if you use Haskell, you can find it in the Prelude. – gnuvince Nov 28 '10 at 16:43
  • Clojure has such a function and since clojure sequences are lazy, you can use it to generate lists of any size. (I dont know the name of the function offhand, so I'll use alternate as an example): (take 4 (drop 1 (alternate :red :green :blue))) would generate the sequence [:green :blue :red :green] –  Dec 04 '10 at 02:35
5

D's scope guards are a useful control structure that isn't seen very often.

helium
  • 1,069
  • 8
  • 13
5

I think I should mention CityScript (the scripting language of CityDesk) which has some really fancy looping constructs.

From the help file:

{$ forEach n var in (condition) sort-order $}
... text which appears for each item ....
{$ between $}
.. text which appears between each two items ....
{$ odd $}
.. text which appears for every other item, including the first ....
{$ even $}
.. text which appears for every other item, starting with the second ....
{$ else $}
.. text which appears if there are no items matching condition ....
{$ before $}
..text which appears before the loop, only if there are items matching condition
{$ after $}
..text which appears after the loop, only of there are items matching condition
{$ next $}
Danko Durbić
  • 6,637
  • 5
  • 32
  • 37
4

Also note that many control structures get a new meaning in monadic context, depending on the particular monad - look at mapM, filterM, whileM, sequence etc. in Haskell.

jkff
  • 16,670
  • 3
  • 46
  • 79
4

ignoring - To ignore exceptions occuring in a certain block of code.

try {
  foo()
} catch {
  case ex: SomeException => /* ignore */
  case ex: SomeOtherException => /* ignore */
}

With an ignoring control construct, you could write it more concisely and more readably as:

ignoring(classOf[SomeException], classOf[SomeOtherException]) {
  foo()
}

[ Scala provides this (and many other Exception handling control constructs) in its standard library, in util.control package. ]

missingfaktor
  • 86,952
  • 56
  • 271
  • 360
  • 2
    Ignoring an exception is normally akin to swallowing a bug. Which is not good for most applications. – Jordão Nov 28 '10 at 04:00
  • @Jordão: [There are cases where you might need to do that](http://programmers.stackexchange.com/questions/16807/is-it-ever-ok-to-have-an-empty-catch-statement) and in such cases, this control construct really makes code cleaner. – missingfaktor Nov 28 '10 at 04:04
  • At the very least, the software should make note that it ignored a certain exception. It might also be a good idea to add some directive to the exception class that indicates it can be ignored, to prevent abusing this feature. – cthulhu Nov 29 '10 at 11:52
4

Something that replaces

bool found = false;
for (int i = 0; i < N; i++) {
  if (hasProperty(A[i])) {
    found = true;
    DoSomething(A[i]);
    break;
  }
}
if (!found) {
  ...
}

like

for (int i = 0; i < N; i++) {
  if (hasProperty(A[i])) {
    DoSomething(A[i]);
    break;
  }
} ifnotinterrupted {
  ...
}

I always feel that there must be a better way than introducing a flag just to execute something after the last (regular) execution of the loop body. One could check !(i < N), but i is out of scope after the loop.

Meinersbur
  • 7,391
  • 1
  • 25
  • 28
  • I really like something like "ifnotinterrupted". – A. Rex Dec 03 '10 at 03:19
  • Python has this: `for` and `while` have an (optional) `else` block that runs only if they complete "naturally" (i.e. without a `break`). – Grant Paul Dec 07 '10 at 02:26
  • @chpwn: Wow, seems that I misinterpreted `else` after loops in Python (I never used it); Thank you for telling me. However, I think "else" is a misnomer. – Meinersbur Dec 07 '10 at 18:48
4

I'd like to see a keyword for grouping output. Instead of this:

        int lastValue = 0;

        foreach (var val in dataSource)
        {
            if (lastValue != val.CustomerID)
            {                    
                WriteFooter(lastValue);
                WriteHeader(val);
                lastValue = val.CustomerID;
            }
            WriteRow(val);
        }
        if (lastValue != 0)
        {
            WriteFooter(lastValue);
        }

how about something like this:

        foreach(var val in dataSource)
        groupon(val.CustomerID)
        {            
            startgroup
            {
                WriteHeader(val);
            }
            endgroup
            {
                WriteFooter(val)
            }
        }
        each
        {
            WriteRow(val);
        }

If you have a decent platform, controls, and/or reporting formatting you won't need to write this code. But it's amazing how often I find myself doing this. The most annoying part is the footer after the last iteration - it's hard to do this in a real life example without duplicating code.

Paul Keister
  • 12,243
  • 4
  • 41
  • 71
  • 1
    +1 I missed this one some time ago when working in VB6. Also, ABAP [has this](http://help.sap.com/saphelp_nw70/helpdata/en/9f/db9f1f35c111d1829f0000e829fbfe/content.htm). – Jordão Dec 03 '10 at 17:39
  • Very interesting, this is the specialization I am thinking of. The At First and At Last for the entire iteration is a nice touch. – Paul Keister Dec 03 '10 at 21:07
  • 1
    In Harbour you can use item:__enumIsFirst and item:__enumIsLast to return a boolean if you are at the first and last item – Bacco Jan 07 '17 at 01:07
3

This is a bit of a joke, but you can get the behavior you want like this:

#include <iostream>
#include <cstdlib>

int main (int argc, char *argv[])
{
  int N = std::strtol(argv[1], 0, 10); // Danger!
  int state = 0;
  switch (state%2) // Similar to Duff's device.
  {
    do {
      case 1: std::cout << (2*state) << " B" << std::endl;
      case 0: std::cout << (2*state+1) << " A" << std::endl; ++state;
    } while (state <= N);
      default: break;
  }

  return 0;
}

p.s. formatting this was a bit difficult and I'm definitely not happy with it; however, emacs does even worse. Anyone care to try vim?

thechao
  • 357
  • 1
  • 8
3

Generators, in Python, are genuinely novel if you've mostly worked with non-functional languages. More generally: continuations, co-routines, lazy lists.

Paul Harrison
  • 275
  • 1
  • 5
3

This probably doesn't count, but in Python, I was upset there was no do loop.

Anto ensure I get no upvotes for this answer, I wind up annoyed at any language I work in for any period of time that lacks goto's.

Tom Ritter
  • 94,954
  • 29
  • 130
  • 168
  • 1
    There's a paper that proves that exceptions can be more powerful than continuations. Continuations are essentially equal in expressive power to `GOTO`. So, if your language has exceptions, it has `GOTO`. – Jörg W Mittag Dec 03 '10 at 01:06
  • @Jörg: Can you please post the link to the paper? – missingfaktor Dec 03 '10 at 03:59
  • 1
    @missingfaktor: The title of the paper is [ *Unchecked Exceptions can be Strictly More Powerful than `Call/CC`* ](http://Lambda-the-Ultimate.Org/node/2966/). Note that, as always with a scientific paper, one has to read very carefully *what* it actually *is* the paper proves. In this particular case, they show that adding SML-style exceptions to the Simply Typed λ-calculus (which is known not to be Turing-complete) makes it Turing-complete, whereas adding `call/cc` to System Fω (which is known to be a strict superset of STλC) doesn't. (The only way to make it TC breaks type soundness.) – Jörg W Mittag Dec 03 '10 at 12:57
  • 1
    This is not just academic trickery, BTW. I know of at least one compiler that used ECMAScript exceptions to implement other control-flow constructs: Microsoft Live Labs' Volta Project was (among other things) a compiler that compiled arbitrary CIL bytecode to ECMAScript source code. CIL (and more generally .NET and C#) has all sorts of control-flow ECMAScript doesn't: `GOTO`, coroutines, threads(!), all of which were implemented using ECMAScript exceptions. – Jörg W Mittag Dec 03 '10 at 13:02
  • 1
    Also note that: "Can be more powerful than" does not necessarily mean "can be used by a human". In particular, I believe that in order to use exceptions like `GOTO` you would have to rewrite your code in continuation-passing-style, then encode your continuation-passing-style into exceptions. – Jörg W Mittag Dec 03 '10 at 13:28
3
for int i := 0 [down]to UpperBound() [step 2]

Missing in every C-derived language.

Please consider before you vote or write a comment:
This is not redundant to for (int i = 0; i <= UpperBound(); i++), it has different semantics:

  1. UpperBound() is evaluated only once

  2. The case UpperBound() == MAX_INT does not produce an infinite loop

Meinersbur
  • 7,391
  • 1
  • 25
  • 28
2
foo();

while(condition)
{
   bar();
   foo();
}
Thea
  • 7,564
  • 6
  • 26
  • 40
Alex
  • 29
  • 2
  • 2
    This doesn't even do what his slit_while is supposed to do. And the real question is what new high level control structures you can think of, not how you could implement them. – helium Nov 28 '10 at 09:24
  • `while (true) { foo(); if (!condition) break; Bar(); }` – Meinersbur Dec 02 '10 at 23:49
2

This is similar to the response by @Paul Keister.

(mumble, mumble) years ago, the application I was working on had lots of variations of so-called control-break processing -- all that logic that goes into breaking sorted rows of data into groups and subgroups with headers and footers. As the application was written in LISP, we had captured the common idioms in a macro called WITH-CONTROL-BREAKS. If I were to transpose that syntax into the ever-popular squiggly form, it might look something like this:

withControlBreaks (x, y, z : readSortedRecords()) {
  first (x) :     { emitHeader(x); subcount = 0; }
  first (x, y) :  { emitSubheader(x, y); zTotal = 0; }
  all (x, y, z) : { emitDetail(x, y, z); ztotal += z; }
  last (x, y) :   { emitSubfooter(x, y, zTotal); ++subCount; }
  last (x) :      { emitFooter(x, subcount); }
}

In this modern era, with widespread SQL, XQuery, LINQ and so on, this need does not seem to arise as much as it used to. But from time to time, I wish that I had that control structure at hand.

Community
  • 1
  • 1
WReach
  • 17,553
  • 3
  • 47
  • 88
1

How about PL/I style "for" loop ranges? The VB equivalent would be:

' Counts 1, 2, ... 49, 50, 23, 999, 998, ..., 991, 990
  For I = 1 to 50, 23, 999 to 990 Step -1

The most common usage I can see would be to have a loop run for a list of indices, and then throw in one more. BTW, a For-Each usage could also be handy:

' Bar1, Bar2, Bar3 are an IEnum(Wazoo); Boz is a Wazoo
  For Each Foo as Wazoo in Bar1, Bar2, Enumerable.One(Boz), Bar3

This would run the loop on all items in Bar1, all items in Bar2, Boz, and Bar3. Linq would probably allow this without too much difficulty, but intrinsic language support might be a little more efficient.

supercat
  • 69,493
  • 7
  • 143
  • 184
1

One of the control structures that isn't available in many languages is the case-in type structure. Similar to a switch type structure, it allows you to have a neatly formatted list of possible options, but matches the first one that's true (rather then the first one that matches the input). A LISP of such such (which does have it):

(cond
   ((evenp a) a)        ;if a is even return a
   ((> a 7) (/ a 2))    ;else if a is bigger than 7 return a/2
   ((< a 5) (- a 1))    ;else if a is smaller than 5 return a-1
   (t 17))              ;else return 17

Or, for those that would prefer a more C-like format

cond 
    (a % 2 == 0): 
        a;     break;
    (a > 7):
        a / 2; break;
    (a < 5):
        a - 1; break;
    default:
        17;    break;

It's basically a more accurate representation of the if/elseif/elseif/else construct than a switch is, and it can come in extremely handing in expressing that logic in a clean, readable way.

RHSeeger
  • 15,196
  • 6
  • 48
  • 41
0

How about iterating with a moving window (of n elements instead of 1) through a list? This is tangentially related @munificent's answer, I think.

Something like

#python
#sum of adjacent elements
for x,y in pairs(list):
    print x + y

def pairs(l):              
    i=0                    
    while i < len(l)-1:    
        yield (l[i],l[i+1])
        i+=1               

It is useful for certain types of things. Don't get me wrong, this is easy to implement as a function, but I think a lot of people try to bring out for and while loops when there are more specific/descriptive tools for the job.

Community
  • 1
  • 1
Ehtesh Choudhury
  • 6,882
  • 5
  • 37
  • 46