2. Flow Control

XploRe offers a variety of possibilities to implement sophisticated structures in your programs. With the commands introduced in the following you are able to make your program react on conditions; you can handle failures while avoiding or provoking a program's stop, and last but not least, you can give your program a well-structured, understandable shape.


2.1 Local and Global Variables


1386 putglobal(x)
generates a global variable x
1389 getglobal(x)
reads a global variable x
1392 existglobal("x")
checks the existence of a global variable x

When you are working with procedures, you have to know whether the variables used in the procedures are accessible in the main program and vice versa. The answer is: XploRe strictly distinguishes between globally and locally defined variables.

Variables in procedures can take on the values of global ones. The procedure then can use the values, change them, and compute various results, but it cannot change the value of the original global variable. However, XploRe helps you to overcome this restriction by using the 1403 putglobal and 1406 getglobal commands. Note that these as well as the 1409 existglobal only work within procedures.

XploRe offers you the possibility to easily transfer a variable from the procedure to the main program. A locally defined variable can then (when the procedure has been run at least once) be accessed and changed in the main program.

Consider the following example:


  proc() = test(a, b) 

    c = a + b       ; computes c as the sum of a and b, 

                    ;    c is now a local variable

    putglobal("c")  ; declares c to be also GLOBAL variable

  endp               

 

  x = 1

  y = 2



  test(x, y)        ; runs the procedure test taking the 

                    ;    values of the globals x and y for 

                    ;    the locals a and b



  c                 ; output of c, c is accessible here 

                    ;    because it has been transferred by 

                    ;    the putglobal command

1417quant07.xpl

It produces the following output

  Contents of c

  [1,]    3

You can also do this the other way around. Normally in a procedure it is not possible to access global variables with the exception of those transferred in the head of the procedure's definition.

For this purpose, you use the 1422 getglobal command, which can transfer the value of a global variable to a local variable. The value can then be used, changed, and results can be computed in the procedure. However, it will not change the global variable in the main program.


  proc() = test(a, b)  

    z = getglobal("z") ; the local z takes on the value of 

                       ;    the global z

    z = a +b +z        ; computes the local z as a sum

    z                  ; output of the "local" z

  endp                 



  x = 1

  y = 2

  z = 3



  test(x, y)           ; runs the procedure test with the 

                       ;    values of x and y for the locals 

                       ;    a and b, respectively, prints the

                       ;    local z



  z                    ; prints the global z

1426quant08.xpl

You obtain this result:

  Contents of z

  [1,]    6

  Contents of z

  [1,]    3

We want to remark here that the existence of a global variable can be checked by 1431 existglobal.


2.2 Conditioning


1445 if - {1448 else} - 1451 endif
conditional branching with two branches

In XploRe, you have the possibility to let the execution of one or several commands depend on a logical condition. XploRe is able to check whether a certain condition is fulfilled or not and then executes the relevant commands in either case. Note that the 1462 if - 1465 else - 1468 endif construct only works within procedures.

For example: To compute the square root of a number, you have to make sure that the number is not negative. To this aim it is advisable to use the following 1471 if - 1474 else - 1477 endif construction:


  proc() = squareroot(a)   

    if(a >= 0)         ; if this condition is true, 

                       ;    XploRe will execute the next 

                       ;    commandline



      sqrt(a)          ; computes the squareroot of a

    else               ;   in case the condition above is not 

                       ;   fulfilled XploRe runs the else branch

      "number is negative"   

                       ; output of the else branch

    endif              ; end of the if construction



  endp                 ; end of the procedure

1481quant09.xpl

You can check the effect if you call this procedure with a negative argument, e.g.


 

  squareroot(-10)      ; runs the procedure with value -10

You obtain the following output:

  Contents of _tmp

  [1,]"number is negative"

By running the procedure squareroot with a positive argument


  squareroot(9)        ; runs the procedure with value 9

you obtain the desired result

  Contents of sqrt

  [1,]    3

Note that the 1486 else branch is optional.


2.3 Branching


1509 switch - 1512 case(x) - 1515 endsw
conditional branching with more than two branches
1518 break
marks the end of a case block inside the switch environment, the procedure is continued at endsw; it can be omitted
1521 default
when the program's counter comes inside a 1524 switch - 1527 endsw construct to this keyword, the following commands are processed in any case; a default statement can be finished by the keyword break, but does not have to be

If you want to make more than two branching points within your program, you may use the 1530 switch - 1533 case - 1536 endsw construction.

The following procedure can distinguish whether its argument is positive, negative or zero:


  proc() = signum(x)       ; defines a procedure named "signum"



    switch                 ; opens the switch branch

      case (x > 0) 

        "positive number"  ; output in the case that x > 0

        break 

      case (x < 0) 

        "negative number"  ; output in the case that x < 0

        break                   

      default

        "number is zero"   ; output in the case that x = 0

        break

    endsw                  ; end of the switch branch

  endp                     ; end of the procedure

1540quant10.xpl

By calling it with different arguments


  signum(10)               ; runs the procedure with value 10

  signum(-5)               ; runs the procedure with value -5

  signum(0)                ; runs the procedure with value 0

you obtain, respectively, the following results

  Contents of _tmp

  [1,]"positive number"

  Contents of _tmp

  [1,]"negative number"

  Contents of _tmp

  [1,]"number is zero"


2.4 While-Loop


1553 while - 1556 endo
repeats one or several commands as long as some condition is fulfilled

You may execute one or several commands repeatedly -- as long as a certain condition is fulfilled. For this purpose you have the 1559 while - 1562 endo loop at your disposal. Note that the 1565 while - 1568 endo construct only works within procedures.

This kind of loop executes one or several commands as long as a logical condition is fulfilled. The following example explains how the factorial of a natural number can be computed using this loop:


  proc(j) = factorial(x) 

                    ; defines a procedure named "factorial"

    j = 1           ; defines the variable j as 1



    while (x >= 2)  ; as long as this condition is fulfilled, 

                    ;    XploRe executes the following commands



      j = j * x     ; computes j as the product of j and x

      x = x - 1     ; reduces x by 1

    endo            ; end of the while loop

  endp              ; end of the procedure

1572quant11.xpl

After calling the procedure with command

  factorial(5)      ; runs the procedure with value 5

you obtain the factorial 5! calculated with the help of the 1577 while - 1580 endo loop:

  Contents of j

  [1,]    120


2.5 Do-Loop


1591 do - 1594 until
repeats one or several commands until the condition is fulfilled

Another possibility for looping inside XploRe procedures is provided by the
[3] 1601 do - 1604 until construction. As with the 1607 while - 1610 endo construct, the 1613 do - 1616 until works only within procedures.

In contrast to the 1619 while - 1622 endo loop, the 1625 do - 1628 until loop executes one or several commands until a certain condition is fulfilled. Since the condition will be checked at the end of the loop, it runs at least once. An example follows:


  proc(j) = factorial(x) ; defines a procedure named "factorial"

    j = 1                ; defines the variable j as 1

    do                   ; opens the do loop

      j = j *x           ; computes j as the product of j and x  

      x = x -1           ; reduces x by 1

    until (x < 2)        ; if the condition is not fulfilled, 

                         ;    the loop will be run again

  endp                   ; end of the procedure

1632quant12.xpl

Calling the procedure with argument 5


  factorial(5)      ; runs the procedure with value 5

produces the desired result:

  Contents of j

  [1,]    120


2.6 Optional Input and Output in Procedures


1647 exist("x") or 1650 exist(x)
checks the existence and the type of a variable x

Both the input and output parameters of a procedure quantlet are in fact lists. For more information on lists, see the Matrix Handling Tutorial.

Due to this list concept, all input and output parameters can be optional. The existence of input parameters can be checked with the 1655 exist command. Table 1 gives all possible return values for 1658 exist.


Table: Return values of 1661 exist.
Value Meaning
-1 object does not exist
0 object exists but is empty
1 object exists and is numeric
2 object exists and is text
3 object exists and is of type XPLTIME
4 object exists and is a display
9 object exists and is a composed object (list)
10 object exists and is a quantlet
> 10 object exists as a quantlet and a variable, e.g. if there is a numeric variable cov and the library("xplore") is loaded exist("cov") results in 11

Consider the following example:


  proc(a,b)=myquant3(x,y)

    error(exist("x")<>1, "input x is not numeric!")

    if (exist("y")==0) ; y does not exist

      y=0

    endif



    switch

      case (exist("y")==2) ; if y is a string

        a=x

        break

      case (exist("y")==1) ; if y is numeric

        a=x

        b=y

        break

      default;

        error(1, "y is neither numeric nor string!")

        break

    endsw

  endp

1665quant13.xpl

The quantlet myquant3 checks first, whether the input x is numeric. Then the existence of y is checked. If y does not exist, it is set to the numeric value 0.

The switch environment produces different results for the cases that y is string or numeric, respectively. We added an error message for the case that y is neither string nor numeric. You may now test the procedure with different input values:


  result=myquant3(1,2)

  result

gives

  Contents of result.a

  [1,]        1 

  Contents of result.b

  [1,]        2

This means that the resulting output object is a list comprising the components result.a and result.b, which contain just the input values.

We can also call myquant3 without specifying the input y, i.e.


  result=myquant3(1)

  result

The result is similar, except that the missing y value is replaced by 0:

  Contents of result.a

  [1,]        1 

  Contents of result.b

  [1,]        0

In the case that a string input y is used, the result is again different:


  result=myquant3(1,"hallo")

  result

produces only one output

  Contents of result.a  

  [1,]        1

To be on the safe side, we assign the output always to the same variable result. This captures the case of two outputs as well as of one output. The function 1670 exist can be used again to check whether the output variable result contains valid component result.b. For our last example


  exist(result.b)

yields

  Contents of exist

  [1,]        0

which indicates that the component result.b is empty.


2.7 Errors and Warnings


1683 error (cond, message)
stops a XploRe program and displays a message
1686 warning (cond, message)
displays a warning message

You have the opportunity to give to the user some hints about problems which occurred when the program is run. With the 1689 error and 1692 warning commands, you can transmit messages to the user of the program.

Both commands check whether a certain condition is true (equal to 1) or not (equal to 0). If the condition is true, a window will be displayed containing a message that has been specified within the command. If the condition is false, the program continues with the next command.

The 1695 error command displays the error box and stops immediately if the given condition is fulfilled. All data and changes to variables that have not been saved before this moment will be lost.


  proc() = test(x)   ; defines a procedure

    error(x<0,"Negative argument!") 

                     ; displays an error box containing the 

                     ;    specified text and stops the program 

                     ;    in case x is negative

    sqrt(x)          ; computes the square root in case the 

                     ;    preceding command did not lead to

                     ;    a break of the program

  endp               ; end of the procedure

1699quant14.xpl

Calling this procedure with the negative argument

  test(-4)           ; runs the procedure with value -4

will display only this error message:

1706

If you do not want to stop the program immediately after checking a problem, you can use the 1708 warning command. In this case there is no data loss. If the condition in the 1711 warning command is fulfilled, the program continues and shows a warning box after it finishes:


  proc() = test(x)   ; defines a procedure



    warning(x<0,"Negative argument!") 

                     ; displays a warning box containing the

                     ;    specified text in case x is 

                     ;    negative at the end of the program 



    sqrt(abs(x))     ; computes the squareroot of abs(x), 

                     ;    whatever the above command found 

                     ;    about x



  endp               ; end of the procedure

1715quant15.xpl

Calling this procedure with the negative argument

  test(-9)           ; runs the procedure with value -9

will produce the result

  Contents of sqrt

  [1,]    3

accompanied with the warning

1722



Method and Data Technologies   MD*TECH Method and Data Technologies
  http://www.mdtech.de  mdtech@mdtech.de