<isolate> and <call>

<isolate> and <call> define or invoke, respectively, block logic that cannot capture values from an enclosing context.

Using the unnamed form: <isolate>

It is often useful to separate small pieces of logic within a larger whole. In the most basic case, the <isolate> block form provides a space to perform a logical task without imposing any side effects on the block within which it appears:

Works

<defblock name="outer" outer_variable="1.61803">
  <isolate inner_variable="3.14159">
    <willbe name="inner_col" value="round({@inner_variable};1)"/>
  </isolate>
  <willbe name="outer_col" value="round({@outer_variable};1)"/>
</defblock>
<call block="outer"/>
In the above example the <isolate> form is used to:
  • Create a new variable called inner_variable
  • Set the value of inner_variable to a value
  • Use the local variable to compute a new column

It should be noted that the variable defined in the opening tag of the <isolate> element is only accessible inside the nested <isolate> form. If outer_variable is referenced within the <isolate> an error will be returned:

Returns an error: Syntax error: Undefined @variable referred to in: round({@outer_variable};1)

<defblock name="outer" outer_variable="1.61803">
  <isolate inner_variable="3.14159">
    <willbe name="inner_col" value="round({@inner_variable};1)"/>
    <!--This willbe returns an error because <isolate> does not have access to @outer_variable-->
    <willbe name="outer_col" value="round({@outer_variable};1)"/>
  </isolate>
</defblock>
<call block="outer"/>

Conversely, the outer <defblock> does not have access to the variable defined by <isolate>. In the following example an error will be returned:

Returns an error: Syntax error: Undefined @variable referred to in: round({@inner_variable};1)+1

<defblock name="outer" outer_variable="1.61803">
  <isolate inner_variable="3.14159">
    <willbe name="inner_col" value="round({@inner_variable};1)"/>
  </isolate>
  <!--This willbe returns an error because the outer <defblock> does not have access to @inner_variable-->
  <willbe name="inner_col_add_one" value="round({@inner_variable};1)+1"/>
</defblock>
<call block="outer"/>

Invoking a named block with <call>

The <call> operation can be used to invoke a named <block> or <defblock> within another block form and produce the same behavior as <isolate>. In the next example, two non-nested <defblock> forms are created. inner_block is called inside outer_block, but only access variables defined in its own context. The example below runs without error and creates two new columns.

<defblock name="inner_block" inner_variable="3.14159">
    <willbe name="inner_col" value="round({@inner_variable};1)"/>
</defblock>
<defblock name="outer_block" outer_variable="1.61803">  
  <willbe name="outer_col" value="round({@outer_variable};1)"/>
  <call block="inner_block"/>
</defblock>
<call block="outer_block"/>

Conversely, if inner_block attempts to access a variable defined in outer_block, or vice versa, running the query will result in an error:

Returns the error: Syntax error: Undefined @variable referred to in: round({@inner_variable};1)

<defblock name="inner_block" inner_variable="3.14159">
    <willbe name="inner_col" value="round({@inner_variable};1)"/>
    <!--An error is throw because the block can't access @inner_variable-->
</defblock>
<defblock name="outer_block" outer_variable="1.61803">  
  <willbe name="outer_col" value="round({@inner_variable};1)"/>
  <!--An error is throw because the block can't access @inner_variable-->
  <call block="inner_block"/>
</defblock>
<call block="outer_block"/>

If it is necessary to use a variable defined in outer_block within inner_block, the desired result can be achieved with call by explicitly defining a parameter in inner_block and passing outer_variable to the inner_block with <call/>:

<defblock name="inner_block" inner_variable="3.14159" capture_outer="">
    <willbe name="inner_col" value="round({@captured_outer};1)"/>
</defblock>
<defblock name="outer_block" outer_variable="1.61803">  
  <willbe name="outer_col" value="round({@outer_variable};1)"/>
  <call block="inner_block" captured_outer="{@outer_variable}"/>
</defblock>
<call block="outer_block"/>

The method above is the best practice for exchanging variables between named blocks.