Show/Hide Toolbars

XSharp

Navigation: X# Documentation > X# Programming guide

Codeblock, Lambda and Anonymous Method Expressions

Scroll Prev Top Next More

X# contains 3 language constructs that are fairly similar yet different.

Codeblocks

Historically the XBase language has known the CodeBlock Type. A codeblock is specified as

 

{| params | expression }

 

The parameters inside a codeblock are of type USUAL and its return value is also of type USUAL.
To evaluate a codeblock you call the Eval() runtime function and pass this function the codeblock and parameters when needed

 

FUNCTION Start() AS VOID
LOCAL cb as CODEBLOCK
cb := { |x, y| x * y}
? Eval(cb, 2,3) // shows 6
WAIT
RETURN

 

In stead of a single expression, you can also use an expression list. The value of the last expression in the list is returned as the result of the codeblock.

 

FUNCTION Start() AS VOID
LOCAL cb as CodeBlock
cb := { |x, y| x += 1, x * y}
? Eval(cb, 2,3) // shows 9
WAIT
RETURN

 

X# has also added the possibility to the language to include a list of statements as "body" of the codeblock. The result of the last statement is returned to the calling code. When the last statement is "Void" then a NIL will be returned:
Note that the closing Curly must be on a line of its own and the first statement must appear on a new line as well.

 

FUNCTION Start() AS VOID
LOCAL cb as CodeBlock
cb := { |x, y|
        x += 1
           ? x
        RETURN x * y
      }
? Eval(cb, 2,3) // prints 3 and shows the result 9
WAIT
RETURN

 

Lambda Expressions

Lamda expressions look a lot like Codeblocks. They are usually used in combination with Delegates.

 

 

DELEGATE MultiPlyInt( x as Int, y as Int) as Int
 
FUNCTION Start() AS VOID
LOCAL lambda as MultiPlyInt
lambda := { x, y => x * y}
? Lambda(2,3) // shows 6
RETURN

 

Parameters are optional and the return type can be VOID, so this works as well

 

DELEGATE DoSomething( ) as VOID
 
FUNCTION Start() AS VOID
LOCAL lambda as DoSomething
lambda := { => Console.WriteLine("This is a Lambda")}
Lambda() // prints the text
RETURN

 

The parameters of a Lambda expression may be typed. This can be convenient for documentation purposes but can also help the compiler to find the right overload for a method:

 

DELEGATE CalcInt( x AS INT, y AS INT) AS INT
 
DELEGATE CalcReal( x AS REAL8, y AS REAL8) AS REAL8
 
FUNCTION Start() AS VOID
TestLambda( { x AS INT, y AS INT => x * y} )
TestLambda( { x AS REAL8, y AS REAL8 => x + y} )
TestLambda( { x , y  => x - y } ) // Which one will be called ?
RETURN
 
FUNCTION TestLambda (lambda AS CalcInt) AS VOID
? "Int", lambda(2,3)
RETURN
 
FUNCTION TestLambda (lambda AS CalcReal) AS VOID
? "Real",lambda(2,3)
RETURN

 

The body of the Lambda may also be a single expression, expression list and a statement list.

Anonymous Method Expressions

These work almost the same as Lambda Expressions.
Take the example below:

 

FUNCTION TestAnonymous() AS VOID
  LOCAL oForm AS Form
  oForm := Form{}
  oForm:Click += DELEGATE(o AS System.Object, e AS System.EventArgs ) {  
                 System.Windows.Forms.MessageBox.Show("Click from AME 1!")  
                 System.Windows.Forms.MessageBox.Show("Click from AME 2!")  
              }  
  oForm:Click += { o,e => System.Windows.Forms.MessageBox.Show("We can also do this with a Lambda!") }  
  oForm:ShowDialog()
  RETURN  

 

The biggest difference between Lambda Expressions and Anonymous Method Expressions is that the parameters to Lambda Expressions do not have to be typed. They will be inferred from the usage. Parameters for Anonymous Method Expressions must always be typed.