12

Similar question was closed on SO.

Sometimes when we're programming, we find that some particular control structure would be very useful to us, but is not directly available in our programming language.

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

The goal here is to get new ways of thinking about structuring code, in order to improve chunking and reasoning.

You can create a wishful syntax/semantic not available now or cite a less known control structure on an existent programming language.

Answers should give ideas for a new programming language or enhancing an actual language.

Think of this as brainstorming, so post something you think is a crazy idea but it can be viable in some scenario.

It's about imperative programming.

Maniero
  • 10,816

22 Answers22

15

OK, this is a fun question.

I would also like to have a general else for while and for loops, for when the condition isn't true on the first test:

while (condition) {
    // process
}
else {
    // condition was never true
}

This avoids the awkward re-computation of the condition or storing it in a variable.

Macneil
  • 8,243
10

Why not mash a few answers into one?

while (expr) {

    // Executed every iteration, unless first{} is present.
    // May be explicitly called rest{} if you like first{} to come first.

    // Blocks may return results, and consequently be used in expressions.
    return expr;

} first {

    // Executed only on the first iteration.

} pre {

    // Executed before every iteration.

} post {

    // Executed after every iteration.

} catch (oops) {

    // All blocks are implicitly try{}ed if followed by a catch{}.

} finally {

    // Executes after the block completes, regardless of exceptions.

} else {

    // Executed if the loop body or rest{} never executes.

} never {

    // Executes only when a client is present.

} drop (bad, worse), // Explicitly ignore certain exceptions.
  until (expr);      // Here, have a post-body condition, too.

An extensible, generalised flow-control construct syntax in an imperative language would be rather useful and entertaining. Until that shows up, guess I'll just use Lisp or something.

Jon Purdy
  • 20,597
7

Control structures as functions.

I want for, if, else, while, etc to be functions, not special structures.

I want return, try/except and goto to be derivatives of continuations.

This of course has less to do with a particular control structure and more to do with how you see control structures in general, the meta of control structures.

6

The linked article definitely gets it right about Donald Knuth's N+1/2 Loops. Expressed in C/C++/Java:

for (;;) {
  get next element;
  if (at the end) break;
  process the element;
}

This is useful for reading lines or characters from a file, testing if you've reached EOF, and then processing it. I'm so used to seeing the pattern for(;;)..if(..)break; appear that it's idiomatic to me. (Before I had read the Knuth article, reprinted in the book Literate Programming, this one used to be a "wtf?".)

Knuth suggested the keywords loop/while/repeat:

loop:
  S;
while C:
  T;
repeat

Where S and T are place holders for a series of zero or more statements, and C is a boolean condition. If there was no S statement then it would be a while loop, and if there was no T statement then it would be a do loop.

This construct itself could be generalized by allowing zero or more while C clauses, making it perfect for expressing infinite loops and then some rarer conditions that would need two checks.

In the same article, Knuth suggested a signaling mechanism that would be a local version of throwing/catching exceptions (as an alternative to using goto).

For me? I wish Java supported tail-call optimization, so that I could express any general control structure as needed.


Update: I forgot to mention that many C/C++/Java programmers get around this one by using an embedded assignment in the condition of the while:

while ((c = getc(f)) != -1) {
   T;
}

Using the terms from Knuth's construct, this is allowable when S and C can be combined into a single expression. Some people hate to see the embedded assignment above, while others hate to see the break in the for (;;) above. But when S and C cannot be combined, such as when S has multiple statements, the for (;;) is the only alternative without repeating code. The other alternative is to simply duplicate the S code:

S;
while (C) {
  T;
  S;
}

Knuth's loop/while/repeat alternative seems much better.

Macneil
  • 8,243
6
unless(condition) {
  // ...
}

does the same thing as:

if(!condition) {
  // ...
}

repeat {
  // ...
} until(condition)

does the same thing as:

do {
  // ...
} while(!condition)
6

The BCPL language had a valueof expression that could be used to turn a sequence of statements into a single expression:

foo(a, b, valueof {some series of statements; resultis v});

Where some series of statements can be anything and the whole valueof evaluates to v.

This could be handy in Java for when you need to compute an argument for calling a this() or super() (which requires that nothing happen before it). Of course, you could just write a separate method, but that might be a pain if you need to pass in many local values for context.

If you are able to use final for variables that are needed, you can already do a valueof in Java using anonymous inner classes:

foo(a, b, new Object(){String valueof(){
    String v ...; some series of statements; return v;}}.valueof());
Macneil
  • 8,243
5

On a different note, I would like to see better support for iterators in programming languages. In particular, for when you want to go down two collections in pairs:

for (String s, Integer i : stringsSet, integersSet) {
    // use the pair (s, i)
}

Some dynamic languages may already have this, or easily support via libraries and macros, but I think this is in the spirit of your question.

If the two sets are not the same size, then it could throw an exception or you could have an else after the loop to signal there was a difference in sizes.

Naturally, you could generalize this for going down three or more lists.


Update: Also useful would be doing the Cartesian product between iterables:

for (String s, Integer i : stringsSet * integersSet) {
    // use the pair (s, i), each s with each i
}

which would be nothing more than nested loops:

for (String s : stringsSet) {
    for (Integer i : integersSet) {
        // use the pair (s, i), each s with each i
    }
}

I'm a little concerned that between the two notations I've provided here that there is a O(n) and O(n^2) difference in the number of pairs, with only the change of a single character.

Macneil
  • 8,243
4

Icon-style expressions with built-in backtracking.

Python gets a lot of the Icon generator benefits - and does a better job of them in general, IMO. And in principle the backtracking was just a kind of exception throw, but it was the simplicity of expressions the rough equivalent of...

x = (a / b) else c;

to handle fail-cases like division by zero.

Where Icon went nuts - no boolean-returning comparison operators. The comparisons always either succeeded or triggered backtracking, and there was some other semantic issue which I'm now desperately trying to remember that... well, let's just say it's probably more repressed than forgotten.

I always thought they should have an if expression with no else part - if (condition, success-value) kind of thing, backtracking if the condition returns false - and drop the weird comparisons.

EDIT I remember - obvious really. A comparison with two arguments either succeeds or fails - it doesn't compute a new value to return. So when it succeeds, what does it return? Answer - one of the arguments. But if you write a > b, which is the logical argument to return - a or b? And what if you write b < a instead? I think it always returned the right argument, which makes as much sense as anything, but it still usually seemed like the wrong argument to me.

4

There is so-called "Dijkstra's Loop" (also called "Dijkstra's Guarded Loop"). It was defined in The Guarded Command Language (GCL). You can find some information about it syntax and semantic in the above Wikipedia article at the section 6 Repetition: do.

Nowadays I actually know one programming language which supports this control struture directly. It is Oberon-07 (PDF, 70 KB). And it supports "Dijkstra's Loop" in thัƒ form of while statement. Take a look at section 9.6. While statements in the above PDF.

WHILE m > n DO m := m โ€“ n 
ELSIF n > m DO n := n โ€“ m 
END

P.S. This is copy of my SO answer.

Wildcat
  • 621
4

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
  • 10,816
3

Continuation Passing Style comes to mind. Then, of course, you'd like to have Tail Call Optimization as well.

3

Seamless thread branching, it has syntax like a function, but executes in a separate thread and can't access data that has not initially been passed to it.

branch foo(data, to, be, processed){
    //code
    return [resulting, data]
}

When a branch is called it will immediately return a handle.

handle=foo(here, is, some, data)

The handle can be used to check if the task is done.

handle.finished() //True if the execution is complete

If the result is requested before the execution is complete the main thread will simply wait.

[result, storage]=handle.result()

This wouldn't cover the more advanced multithreading scenarios, but rather provide an easily accessible way of beginning to utilize multiple cores.

aaaaaaaaaaaa
  • 1,066
3
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
  • 10,816
2

I sometimes find myself writing a loop that needs to do something different during the first iteration. For example, displaying <th> tags instead of <td> tags.

I handle this situation with a boolean flag. Something like this:

first = true

while (some_condition)
    if (first)
        do_something
        first = false
    else
        do_something_else

It seems silly to check the value of first on every iteration when it's going to be false most of the time.

I'd like to have a looping option to specify a different loop body on the first iteration. There would be no need for a separate variable. The compiled code wouldn't need one, either, because the generated code would have two bodies, one for the first iteration and one for the rest.

Barry Brown
  • 4,095
1

[ copied from my own answer on stackoverflow ]


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. ]

1

Instead of:

switch(myEnum) {
  case MyEnum.Val1: do1(); ...
  case MyEnum.Val2: do2(); ...
....

Do it the Python, or now the C# way as well:

action = val2func[myEnum]
action()

Scala has lots of new features.

Finally, languages such as Clojure can be extended to provide the extra functionality.

Job
  • 6,459
1

I have two ideas.

Often I find that I am repeating myself in catch blocks. This can be somewhat helped through extracting methods, but that can cause unnecessary clutter if the methods are very short or otherwise not worthy of a method. So, it would be nice to nest catch blocks:

try {
    // Save something
} catch (Exception e) {
    // Something we do for all Exceptions
    catch (ProcessingException e) {
        // Something we do for all Processing exceptions
        catch (DBExcpetion e) {
            // DBExceptions are a subclass of ProcessingException
        }
        catch (BusinessRuleException e) {
            // BusinessRuleExceptions are also a subclass of ProcessingException
        }
    }
    // Something we do after specific sub class Exceptions
 }

In web programming I am also often find myself often doing something like this (this isn't a real example so don't analyze fictional cases):

Account a = getSavedAccount();
if (a == null) {
    a = getAccountFromSessionId();
}
if (a == null) {
    a = getAccountFromCookieId();
}
if (a == null) {
    a = createNewAccount();
}

In Javascript (well, ECMAScript, and maybe others that I am unfamiliar with), since any value can be evaluated as a condition, || can help.

var a = getAFromLocation1() || getAFromLocation2() || default;

I really like how that looks, and I wish more languages, particular some on the server side, had support for it. (PHP can evaluate anything as a condition, but converts the whole conditional expression to a boolean instead of preserving the value. I don't know about Python or Ruby.) It could get unwieldy after three cases or so, but if you have more than three cases, you might also have a bad software design.

Nicole
  • 28,243
1

Generalised switch has said above :

 switch(x){
  predicate1:
     dosomething();
  predicate2:
     dosomethingelse();
 }

In Haskell :

  switch' :: a -> [(a -> Bool, b)] -> b
  switch' a [] = undefined
  switch' a (f,b):xs = if f a
                     then b
                      else switch' a xs
0

In C# I would like to use simple switch () { ... }, but extendible with such expressions:

switch (value)
{
  // string-based operators:
  case begins "Maria": // to catch Maria Carey
    break;
  case ends "Washington": // to catch George Washington
    break;
  case like "ph": // to catch Phil, Phillip, Sophie
    break;
  case between "Aaron" and "April": // to catch all names between
    break;

  // use non-static variables in case expression:
  case Dao.GetDefaultBabyName():
    break;

  // continuable cases without breaking
  case "John":
    bonus = 25;
  case "Peter":
    salary = 500;
    break;

  // jumps between cases
  case "Aleron":
    // do something
    break;
  case "Bella":
    // do something
    jump "Aleron";
    break;

}

And so on. The same with numbers or other types (that supports IComparable, IConvertible, ...)

This might make my code more laconic and readable.

Genius
  • 601
0

It is a fun question, as @Macneil said.

My favorite unusual control structure, which I (humble cough) discovered, is differential execution.

It has certain uses. For me, the overwhelming use is in programming user interfaces, which is an instance of the more general problem of maintaining redundant data in correspondence. On the one hand, there is application data, and on the other, there are UI controls, that need to be kept in agreement. This sounds like "binding" but there's actually a lot more to it.

Usually I implement it by macros in C or C++. In C# I have to do it by hand-expanding statements. That is a pain, but it works.

Once I implemented it in terms of Lisp macros, and then it was very clean. It did not require carefulness on the part of the programmer. I could have done the same thing in any other structured language if I took the trouble to write a complete parser and then generate all the right stuff. That's a big project, and I haven't done it.

Mike Dunlavey
  • 12,905
0

"Traditional" control structures like for are about controlling the working man, keeping him subservient to the corrupt ideologies of the ruling capitalist elite. That's why I use alternative control structures like ph0r instead. It's like for, but more radical: You won't catch ph0r wearing a suit and tie, spouting some corporate BS. ph0r keeps it real, man.

Fight the power!

0

Simplest for loop-

for(100)
{
    //Will run for 100 times
}


for(i)
{
    //Will run for i times while i must be a positive integer
}


for(i as a)
{
    //Will run for i times while i must be a positive integer
    //and a is the incremental loop variable starting from 0 and 
    //scoped within the loop
}


for(i as a=2)
{
    //Will run for i times while i must be a positive integer
    //and a is the incremental loop variable starting from 2 and 
    //scoped within the loop
}
Gulshan
  • 9,532