Block - vilinski/nemerle GitHub Wiki

Intro

This page discusses proposed block construct. Please feel free to add any comments.

Description

The block construct looks like this:

 foo: {
   ...
   ...
 } 

It starts with a label (an identifier) followed by : colon and a sequence of expressions. The value of the block is the value of the last expression in its sequence, except when we jump out of the block, using its label. Such a jump transfers control flow to the end of the block returning value passed to the label.

For example:

 def x = 
   foo: {
        when (some_cond)
            foo (3);
        qux ();
        42
   };

works the same as:

 def x = if (some_cond) 3 else
         {
           qux ();
           42
         };

(which is clearly a better code structure in this very place :-)

Common usage

Blocks are good replacement for the return, break and continue statements known from C.

For example the following Nemerle code:

 foo() : int 
 {
    return: 
    {
      when (some_cond)
          return(42);

      do_some_stuff();

      33
    }
} 

simulates the following C# code:

int foo() 
{
  if (some_cond)
  return 42;

  do_some_stuff();

  return 33;
} 

While the following:

 break: 
 {
    while (cond)
    {
      when (some_cond)
        break();

      some_stuff();
    }
} 

simulates:

while (cond) 
{
  if (some_cond)
  break;

  some_stuff();
} 

As you can see we have used here the void literal. It is however also possible to return some more meaningful value:

 def has_negative =
         res:
         {
           foreach (elem in some_collection)
             when (elem < 0)
               res(true);

           false
         }

which give us possibility to have localized return-like statement inside the expressions.

Nemerle.Imperative

Special implicit blocks are created around functions and loops. After importing the Nemerle.Imperative namespace, you have access to regular break, continue and return known from C.

using Nemerle.Imperative;

def foo1 (x) 
{
  when (x > 3)
    return x * 17;

  mutable y = x;
         
  while (y > 0)
  {
    when (y % 33 == 0)
      continue;

    when (some_cond)
      break;

    when (some_other_cond)
      return y;
  }
}

def foo2 () 
{
  when (some_cond)
    return;

  foo1 (3);
} 

As in C break exits nearest enclosing loop and continue starts the next iteration.

return exits nearest enclosing function, but functions created by the compiler to implement standard loops don’t count!