Control structures
The extension function language provides the usual statements to control program execution.
- If Then Else
- While Do and Repeat Until
- Numeric For
- Break
- Goto
If Then Else
If statements select blocks of statements to execute based on one or more conditions. There are three forms:
If then Form
if expression then
statements to execute if expression is not false or nil
end
<!--NeedCopy-->
If then else Form
if expression then
statements to execute if expression is not false or nil
else
statements to execute if expression is false or nil
end
<!--NeedCopy-->
If then elseif else Form
if expression1 then
statements to execute if expression1 is not false or nil
elseif expression2 then
statements to execute if expression2 is not false or nil
. . .
else
statements to execute if all expressions are false or nil
end
<!--NeedCopy-->
Example:
if headers[name] then
local next_value_index = #(headers[name]) + 1
headers[name][next_value_index] = value
else
headers[name] = {name .. ":" .. value}
end
<!--NeedCopy-->
Note:
- The expression is not enclosed in parentheses as is the case in C and Java.
- There is no equivalent to the C/Java switch statement. You have to use a series of if elseif statements to do the equivalent.
While Do and Repeat Until
The while and repeat statements provide loops controlled by an expression.
while expression do
statements to execute while expression is not false or nil
end
repeat
statements to execute until expression is not false or nil
until expression
<!--NeedCopy-->
Example for while:
local a = {1, 2, 3, 4}
local sum, i = 0, 1 -- multiple assignment initializing sum and i
while i <= #a do -- check if at the end of the array
sum = sum + a[i] -- add array element with index i to sum
i = i + 1 -- move to the next element
end
<!--NeedCopy-->
Example for repeat:
sum, i = 0, 1 -- multiple assignment initializing sum and i
repeat
sum = sum + a[i] -- add array element with index i to sum
i = i + 1 -- move to the next element
until i > #a -- check if past the end of the array
<!--NeedCopy-->
Of course it is possible to write a loop that does not terminate, for example, if you omit the i = i + 1 statement in either of these examples. When such a function is executed, Citrix ADC will detect that the function did not complete in a reasonable time and will kill it with a runtime error:
Cpu limit reached. Terminating extension execution in [[string "function extension function..."]]: line line-number.
will be reported in /var/log/ns.log.
Numeric For
There are two types of for loops. The first is the numeric for, which is similar to the usual use of the for statement in C and Java. The numeric for statement initializes a variable, tests if the variable has passed a final value, and if not executes a block of statements, increments the variable, and repeats. The syntax for the numerical for loop is:
for variable = initial, final, increment do
statements in the loop body
end
<!--NeedCopy-->
where initial, final, and increment are all expressions that yield (or can be converted to) numbers. variable is considered to be local to the for loop statement block; it cannot be used outside of the loop. increment can be omitted; the default is 1. The expressions are evaluated once at the beginning of the loop. The terminating condition is variable > final if the increment is positive and variable < final if the increment is negative. The loop terminates immediately if the increment is 0.
Example (equivalent to the while and repeat loops in the preceding section):
sum = 0
for i = 1, #a do -- increment defaults to 1
sum = sum + a[i]
end
<!--NeedCopy-->
The second type of for loop is the generic for, which can be used for more flexible types of loops. It involves the use of functions, so will be discussed later after functions have been introduced.
Break
The break statement is used inside a while, repeat, or for loop. It will terminate the loop and resume execution at the first statement after the loop. Example (also equivalent to the preceding while, repeat, and for loops):
sum, i = 0, 1
while true do
if i > #a then
break
end
sum = sum + a[i]
i = i + 1
end
<!--NeedCopy-->
Goto
The goto statement can be used to jump forward or backward to a label. The label is an identifier, and its syntax is ::label::. The goto statement is goto label. Example (once again equivalent to the preceding loops):
sum, i = 0, 1
::start_loop::
if i > #a then
goto end_loop -- forward jump
end
sum = sum + a[i]
i = i + 1
goto start_loop -- backwards jump
::end_loop::
. . .
<!--NeedCopy-->
There has been a long running controversy over using gotos in programming. In general, you should try to use the other control structures to make your functions more readable and reliable. But occasional judicious use of gotos may lead to better programs. In particular, gotos may be useful in handling errors.