Why you cannot use vipers within expression parameters

(Not Related to a Specific Release) - ...

Before explaining why you can't use vipers within expression parameters, let's first of all, clarify the main viper concepts.

Expression

An expression is a mathematical formula with a single result.

Examples of expressions:

  CopyCode image Copy Code
3+4 => 7
'hello'+' '+'world' => 'hello world'
true || false => true

ViperMethod

A vipermethod is a mathematical function call syntax with zero or more parameters. The function syntax consists of a function name, immediately followed by braces. The braces can optionally contain one or more, comma separated, arguments (parameters). Vipermethod parameters are, in fact, expressions. They can contain literal values, but the also complex formula's including nested vipermethod calls.

Examples of vipermethods:

  CopyCode image Copy Code
sys.eval(3+4)
string.substring('hello world', 5)

Viper

A viper is basically a vipermethod enclosed within curly braces. This makes the vipermethod an executable entity; it is detected by the SXML engine and, after execution, replaced by its result. Contrary to macro's which are xml elements, vipers can be used within regular text and within xml attributes. This makes the viper syntax a powerful and versatile syntax.

Examples of vipers:

Smartsite SXML CopyCode image Copy Code
{datetime.now()}
{string.toupper('hello')}

The viper syntax was carefully chosen; its purpose is to make the vipermethod recognizable by the SXML engine and to avoid conflicts with regular text. A viper starts with a specific sequence of characters {vipermethodname( and always ends with )}.

Expression and condition parameters

The expression and condition parameter are examples of macro parameters of type Expression Syntax. These parameters accept expressions with a boolean result.

This is an example of an if-condition test using both the macro and viper notation.

Smartsite SXML CopyCode image Copy Code
<se:if expression="3*2==6">equal</se:if>
{sys.iif( 3*2==6, 'equal' )}

Using vipers within the expression macro parameter

Since vipers and macro's are both executable entities, using a viper within the expression parameter of a macro, would imply, that the value read by the macro would be the result of the viper.

In this example, the vipermethod {myexpression()} would have to return an expression, which in turn can be evaluated by the if-macro.

Smartsite SXML CopyCode image Copy Code
Incorrect syntax: <se:if expression="{myexpression()}">true</se:if>

When the SXML engine parses this macro, it will encounter the viper {myexpression()} which by itself is executable. It would then execute the viper and feed the result to the if-macro.

While is is technically possible, we found this syntax to be confusing and with no added value. Therefore, we have decided not to allow it.

While it might seem somewhat confusing at first, the behavior is logical and the concept of parameter indirection is similar to many other programming languages (for example functional calls versus function pointers).

sys.eval() versus string.eval()

Although it is a different case, there is a similar difference between the vipers sys.eval() and string.eval().

Smartsite SXML CopyCode image Copy Code
{sys.eval(2*3)} => 6
{string.eval( '2*3' )} => 6

The viper sys.eval() expects an expression as its parameter, string.eval() expects a string parameter.

When the SXL engine parses the parameter of sys.eval(), it evaluates the expression and feeds the result to the sys.eval() viper. If you think about this, you will understand that the sys.eval() viper itself has no work to do; it has an empty implementation!

On the other hand, when the SXML engine parsers the parameter of string.eval() it read the parameter as a string or (tries to) convert it to a string. It then feeds this string to the string.eval() viper. The string.eval() viper receives the string parameters and then calls the expression evaluator to execute the expression and return the result.

With this knowledge, you should now be able to predict the outcome of the following exercise:

Smartsite SXML CopyCode image Copy Code
{buffer.set( a, '2*3' )}
1: result:{sys.eval($a)} resulttype:{sxml.gettypename( sys.eval($a) )}
2: result:{string.eval($a)} resulttype:{sxml.gettypename( string.eval($a) )}