JudoScript.COM Design principles of Judo the sport and the language
HomeJudo LanguageJuSP PlatformJamaica Language 
Judo ReferenceJuSP ReferenceWiki/WeblogTutorials/PresentationsDownloadsGoodiesFeedback  
Book: The Judo Language 0.9
 








In this chapter:

Chapter 6. Flow Control

By James Jianbo Huang

printer-friendly version
Synopsis: This chapter introduces all the flow control mechanisms of general programming. In addition to the flow control statements such as if-else, switch-case-default, while and for loops, function and exception handling are also covered.

 
Basic Flow Control Statements

Types of Judo Statements

In Judo, statements include simple statements, block statement, compound statements and event-driven statements.

Simple statements
Simple statements perform specific tasks. For example, the assignment statement assigns a value to a variable or field; a return statement returns from a function or method. Simple statements in Judo can actually be quite complicated, such as the JDBC statements:

executeQuery qry:
  SELECT * FROM emp WHERE first_name = ?
; with @1 = 'James';

Block statement
A number of statements can be grouped and surrounded by { and } and form a block. Blocks have their own variable scope.

Block ::= { ( Statement )* }

Blocks can also be a part of other compound statements that are discussed in this chapter. Blocks can also have catch and finally clauses, discussed in Exception Handling.

Compound statements
Compound statements are those that may contain or require other statements for processing based on different conditions and/or in different situations. The enclosed statements are usually organized in block statements. In the general programming area, the flow control statements (such as if-else and loops) are all compound statements. Many functional statements are also compound statements.

Event-driven statements
Some of Judo's functional statements use an event-driven programming model; those statements are event-driven statements. For instance, the guiEvent statement, the SGML and XML statements. The following is an example of SGML statement:

do 'http://www.yahoo.com' as sgml {
<a>:   if $_.href != null { println $_.href; }
<img>: println $_.src;
}

In this SGML statement, each SGML tag encountered is treated as an "event"; you as a programmer provides an event "handler", which is a series of statements, for each "event".


If-Else Statement

The if-else statement has this syntax:

IfElse ::= if Expr Block ( ( else if | elif ) Expr Block )* [ else Block ]

The Expr's are evaluated to boolean values; if true, the chunk of code that follows will be executed. If-else statement is straightforward and is one of the most frequently used statement. There is only one catch: the blocks following if, elif and else expressions do not define new scopes. If you declare local variables in these blocks, the scope for these variable is actually the scope that contains the if-statement. To avoid confusion, do not declare local variables in any of these blocks. For instance,

if foo() {
  var tmp = 5;
  println 'foo() returns true.';
} else {
  println 'foo() returns false.';
}
println tmp;

In the last line, tmp may or may not be defined, depending on the boolean result of the foo() call. A better way is to move the var tmp declaration out.


Switch Statement

The syntax for the switch statement is:

Switch ::= switch Expr { ( CaseClaus )* }
CaseClause ::= ( case Expr | default ) : ( Statement )*

No more than one default clause is allowed. The Expr following switch is evaluated and checked against values specified in each case clause; if a match is found, the chunk of code is executed; if no match is found and the default clause is present, execute the chunk of code for default; otherwise, simply finish the statement.

The values in the case clauses are usually constant values but actually can be any expressions; the value types can be anything, such as primitive types like integer, number, string, date/time, and Java objects. The match between the switch value and case values tries the comparisons with different types and is carried out in this order: Java object, number and date/time, and string. The following example demonstrates this:

Listing 6.1 stmt_switch.judo
values = [ 9,
           Date(2001,11,20),
           new java::HashMap,
           'uvw',
           'XYZ',
           '{}'
         ];

for a in values {
  switch a {
  case 9:                 println 'CASE OF number: ', a; break;
  case 'uvw':             println 'CASE OF string: ', a; break;
  case Date(2001,11,20):  println 'CASE OF Date:   ', a; break;
  case new java::HashMap: println 'CASE OF Java:   ', a; break;
  default:                println 'DEFAULT:        ', a; break;
  }
}

The values is an array of values of different types; each value is run against the switch statement. The result is:

CASE OF number: 9
CASE OF Date:   11/20/01 12:00 AM
CASE OF Java:   {}
CASE OF string: uvw
DEFAULT:        XYZ
CASE OF Java:   {}

What happened to the value of '{}'? It is a string and happens to match new java::HashMap because they both share the same stringn representation, {}. In most situations, the case values are numbers or strings.

Statements for each case and default normally ends with a break statement. If no break statement is present at the end, the program continues on to the statements in the next case or default; you can have no statements for certain case and/or default clauses to share a same chunk of code. For instance,

switch x {
case 1:
case 2:
case 3:  println 'In [1,3]';          break;
case 4:
case 5:
case 6:  println 'In [4,6]';          break;
default: println 'Outside of [1,6];'; break;
}

Note that the case values do not have to be constants; they can be any expression. This may be used for dynamic matching. The following example uses the switch statement in a function (which will be discussed shortly in this chapter); it is not a practical function for the purpose of its name.

Listing 6.2 stmt_switch2.judo
for i from 0 to 100 {
  isPowerOf i, 3;
}

function isPowerOf x, base {
  base2 = base  * base;
  base3 = base2 * base;
  base4 = base3 * base;
  base5 = base4 * base;
  base6 = base5 * base;

  switch x {
  case 0:
  case base:
  case base2:
  case base3:
  case base4:
  case base5:
  case base6: println x, ' is a power of ', base; break;
  }
}

The result is:

0 is a power of 3
3 is a power of 3
9 is a power of 3
27 is a power of 3
81 is a power of 3

While and Do-While Loops

The while and do-while statements have the following syntax:

While ::= while Expr Block
DoWhile ::= do Block while Expr ;

The meaning of these two statements are self-evident. The following example tests both:

Listing 6.3 stmt_while.judo
println 'while() {}';
a = 3;
while a >= 0 {
  println a;
  --a;
}

println;
println 'do {} while.';
do {
  println a;
  a++;
} while a < 2;

The result is:

while() {}
3
2
1
0

do {} while.
-1
0
1

For and Repeat Loops

Judo has three for loop statements.

The generic for loop

The syntax for the generic for loop is:

ForLoop ::= for [ ( ] [ ExprList ] ; [ Expr ] ; [ ExprList ] [ ) ] Block
ExprList ::= Expr ( , Expr )*

This form of for loop is the same as the for statement in Java or C/C++. It runs the first list of expressions sort of like initialization, then check on the boolean expression in the second place; if true, the block is executed, and at the end the expression list in the third place is executed. So, for the following pseudocode:

for init(); cond(); postproc() {
  do_work();
}

it is equivalent to:

init();
while cond() {
  do_work();
  postproc();
}

This is an example:

Listing 6.4 forloop.judo
for a=0; a<3; ++a {
  println a;
}

The for-from-to loop

This statement is to loop through a series of numbers as specified. The syntax is:

ForFromTo ::= for [ ( ] INDENTIFIER [ from Expr ] ( do | downto ) Expr [ step Expr ] [ ) ] Block

The loop number can be ascending (with the to clause) or down (with the downto clause). If the from clause is missing, by default it starts with 0. If the step is not specified, the step is defaulted to 1. Step can never be negative; if negative value is specified, its absolute value is used instead. The following program demonstrates varios usages:

Listing 6.5 for_fromto.judo
print 'for [from 0] to 3:           ';
for a to 3 { print a, ' '; }
println;

print 'for from 3 to 5:             ';
for a from 3 to 5 { print a, ' '; }
println;

print 'for from 3 to 10 step 2:     ';
for a from 3 to 10 step 2 { print a, ' '; }
println;

print 'for from 10 downto 5 step 2: ';
for a from 10 downto 5 step 2 { print a, ' '; }
println;

The result is:

for [from 0] to 3:           0 1 2 3
for from 3 to 5:             3 4 5
for from 3 to 10 step 2:     3 5 7 9
for from 10 downto 5 step 2: 10 8 6

The for-in loop

The for-in statement is to iterate through collection data structures. Collections include built-in data structures such as Array, LinkedList, Set and Object. Java arrays and instances of java.util.Iterator, java.util.Enumeration, java.util.Collection, java.util.List and java.util.Map can also be iterated with for-in statement. In the case of Judo Object and Java java.util.Map subjects, their keys are iterated. The syntax of for-in statement is:

ForIn ::= for [ ( ] INDENTIFIER in Expr [ backward ] [ from Expr ] ( do | downto ) ExprList [ step Expr ] [ ) ] Block

The backward and from/to apply only to fixed-length collections such as Array, Java arrays and java.util.List instances. The following example shows some of the usages:

Listing 6.6
println 'Iterating Array:';
a = [ 1, 2, 3 ];
for x in a {
  println loopIndex(), ': ', x;
}

println nl, 'Iterating Java array:';
a = new java::int[]{ 10, 20, 30 };
for x in a {
  println loopIndex(), ': ', x;
}

println nl, 'Iterating java.util.ArrayList:';
a = new java::ArrayList;
a.add(100);
a.add(200);
a.add(300);
for x in a {
  println loopIndex(), ': ', x;
}

println nl, 'Iterating with range:';
a = [ 1, 2, 3, 4 ];

print "--- for in                 ";
for e in a { print e, ' '; }

print nl, "--- for in backward        ";
for e in a backward { print e, ' '; }

print nl, "--- for in from 1          ";
for e in a from 1 { print e, ' '; }

print nl, "--- for in to 1            ";
for e in a to 1 { print e, ' '; }

print nl, "--- for in from 1 to 2     ";
for e in a from 1 to 2 { print e, ' '; }

print nl, "--- for in from 2 downto 1 ";
for e in a from 2 downto 1 { print e, ' '; }

print nl, "--- for in downto 1        ";
for e in a downto 1        { print e, ' '; }
println;

The result is:

Iterating Array:
0: 1
1: 2
2: 3

Iterating Java array:
0: 10
1: 20
2: 30

Iterating java.util.ArrayList:
0: 100
1: 200
2: 300

Iterating with range:
--- for in                 1 2 3 4
--- for in backward        4 3 2 1
--- for in from 1          2 3 4
--- for in to 1            1 2
--- for in from 1 to 2     2 3
--- for in from 2 downto 1 3 2
--- for in downto 1        4 3 2

The repeat statement
If you simply want to repeat certain operations for a number times, the repeat statement is an easy one.

Repeat ::= repeat Expr [ times ] Block


Break, Continue and Loop Index

The break and continue statements
In loops, you can use the break statement to break the loop, or continue statement to skip the rest of the statement in the current iteration and go to the start of next iteration. The syntax for these statements is:

BreakContinue ::= ( break | continue ) [ IDENTIFIER ] ;

The optional IDENTIFIER is a label name for a loop to break or continue from within a nested loop. The following is an example:

Listing 6.7 breakcont.judo
aloop:
  for i from 0 to 5 {
    for j from 1 to 5 {
      if i+j < 5 {
        continue aloop;
      } else if i+j >= 10 {
        break aloop;
      }
      println i, '-', j;
    }
  }

The result is:

4-1
4-2
4-3
4-4
4-5
5-1
5-2
5-3
5-4

Loop index
All loop statements, including the general programming flow control and special-purpose statements to be discussed later in the book, have a loop index. The loop index starts at 0 for the first iteration and increments thereafter. This loop index is accessible via the system function, loopIndex(). It can take a negative integer number to return the loop index of the enclosing loop statement in case of nested loops.

Listing 6.8 loopidx.judo
for i from 1 to 3 {
  for j from 2 to 5 {
    println ' outer loop: ', loopIndex(-1),
            ' inner loop: ', loopIndex();
  }
}

The result is:

  outer loop: 0  inner loop: 0
  outer loop: 0  inner loop: 1
  outer loop: 0  inner loop: 2
  outer loop: 0  inner loop: 3
  outer loop: 1  inner loop: 0
  outer loop: 1  inner loop: 1
  outer loop: 1  inner loop: 2
  outer loop: 1  inner loop: 3
  outer loop: 2  inner loop: 0
  outer loop: 2  inner loop: 1
  outer loop: 2  inner loop: 2
  outer loop: 2  inner loop: 3

This loopIndex() function can be quite useful in loops that do not have an explicit loop indicator; without it, sometimes you would need to use an explicit counter variable. For instance, the following program prints out lines starting at line number 5 in a file:

do file_name as lines {
  if loopIndex() < 5 { continue; }
  println $_;
}

The do .. as lines statement is covered later.


 
Functions and Function Variables

Judo functions organize code into reusable units. A function can take 0 or more parameters, and return a value. They can be built-in system functions or user-defined functions. The syntax for user-defined function declaration is:

Function ::= function IDENTIFIER [ ( ] params [ ) ] { ( Statement )* }
params ::= param ( , param )* [ , .. ] | .. | < Expr >
param ::= IDENTIFIER [ = Expr ]

The same syntax is used for methods within user-defined classes; there are some fundamental differences between functions and class methods, which will be discussed in chapter 10. Object-Oriented Programming.

The parentheses around parameters are not required; if parentheses are used, the right parenthesis must match the left one. Functions always return a value; the return statement can return a value and exit the function. If no return statements are called, the function code will fall out of scope and exit, returning undefined. Functions, like any declarations in Judo, can appear anywhere, that is, you can call a function before it is declared. The following is the famous Hanoi Tower problem followed by the result of a test run.

Listing 6.9 hanoi.judo
cnt = 0;
hanoiTower(4, 'A', 'B', 'C');

function hanoiTower N, src, aux, dst {
  if N == 0 { return; }
  hanoiTower(N-1, src, dst, aux);
  println 'step ', ++cnt :>2, ':  ', src, ' => ', dst;
  hanoiTower(N-1, aux, src, dst);
}

The Tower of Hanoi puzzle was invented by the French mathematician Edouard Lucas in 1883. There are three pegs; initially a number of disks of different sizes are stacked on one peg; the objective is to transfer the entire tower to another peg, moving only one disk at a time and never a larger one on top of a smaller. This is a well-known recursive algorithm. In hanoi.judo, we used a global variable, cnt, to track the history of the transfers. The following is the result of moving an initial tower of 4 disks.

step  1:  A => B
step  2:  A => C
step  3:  B => C
step  4:  A => B
step  5:  C => A
step  6:  C => B
step  7:  A => B
step  8:  A => C
step  9:  B => C
step 10:  B => A
step 11:  C => A
step 12:  B => C
step 13:  A => B
step 14:  A => C
step 15:  B => C

Function Parameters

Function parameter names are the same as variable names. Parameters may have default values. Function calls can take any number of parameter values. If the number of passed values is less than the number of declared parameters, the missing parameters take the default values in the function declaration; if no default values specified, null is used. If the number of passed values is more than the number of declared parameters, the extra parameters are stored in an array in the predefined local variable, $$args.

To explicitly declare that a function takes variable number of parameters, you may end the parameter list with two dots (..); this has no further meaning.

During function calls, parameters are pass-by-value for primitive Judo data types (including integer, number, date and time and string), and pass-by-reference for other object types.

Listing 6.10 var_params.judo
function inc x, delta=1, .. {
  ret = x + delta;
  if $$args != null {
    for x in $$args { ret += x; }
  }
  return ret;
}
println inc(2);
println inc(2,2);
println inc(2,2,2);

function sum .. {
  ret = 0;
  for x in $$args { ret += x; }
  return ret;
}
println sum(1,2,3,4,5,6,7,8,9);

function oneparam a {
  println '---', nl, 'The parameter: ', a;
  if $$args != null {
    println unit($$args.length, 'useless parameter');
  }
}
oneparam('abc');
oneparam('abc', x, y, z);

The result is:

3
4
6
45
----
The parameter: abc
----
The parameter: abc
3 useless parameters

Dynamic Function Parameters

Judo allows you to dynamically create a parameter list in an array, and use that array as function call parameters through the {{ }} syntax.

Listing 6.11 dyn_params.judo
function sentence subj, verb, obj, .. {
  print subj, ' ', verb, ' ', obj;
  for x in $$args { print ' ', x; }
  println '.';
}

params = [ 'James', 'wrote', 'Judo' ];
sentence( {{params}} );

params = [ 'He', 'uses', 'Judo', 'day-in', 'and', 'day-out' ];
sentence( {{params}} );

In the example, the functionsentence() prints out all its parameters separated by spaces. The first three parameters are named, and it handles variable number of parameters. When called with dynamic parameters in an array, the elements of array are taken as individual parameters and the result of execution is:

James wrote Judo.
He uses Judo day-in and day-out.

Function Variables

A function variable is a variable that references a function. A function reference is obtained by the & operator. They can be assigned to variables or passed as paramter values to other functions.

To call a function reference stored in a variable, you can simply invoke the function with the variable name. If the function reference is stored in an array element, use that array element. If the function reference is stored as a value for a key in an Object, use the key name to invoke the function. The following example demonstrates all these situations.

Listing 6.15 fxn_var.judo
function foo1 a, b { return a + b; }
function foo2 a, b { return a * b; }
function whichFoo f, a, b { return f(a,b); }

println 'whichFoo(&foo1, 2, 3) = ', whichFoo(&foo1, 2, 3);
println 'whichFoo(&foo2, 2, 3) = ', whichFoo(&foo2, 2, 3);

x = [ &foo1, &foo2 ];
println 'x = ', x;
println 'x[0](2, 3) = ', x[0](2, 3);
println 'x[1](2, 3) = ', x[1](2, 3);

y = { fxn1 = &foo1, fxn2 = &foo2 };
println 'y = ', y;
println 'y.fxn1(4, 6) = ', y.fxn1(4, 6);
println 'y.fxn2(4, 6) = ', y.fxn2(4, 6);

The only ambiguous situation is that, if there is a function defined with the same name as a variable that holds a function reference, the defined function will be accessed. To remedy this situation, Judo uses the -> operator to explicitly invoke a function referenced in a variable as follows:

function foo1 a, b { return a + b; }
function foo2 a, b { return a * b; }
function whichFoo f, a, b { return f(a,b); }

println 'whichFoo->(&foo1, 2, 3) = ', whichFoo->(&foo1, 2, 3);
println 'whichFoo->(&foo2, 2, 3) = ', whichFoo->(&foo2, 2, 3);

Function variables are important in Judo. Many data structures have methods that take particular function variables to do tasks such as sorting, filtering and transformation. For instance, Array's sort() method can take a function reference which takes two parameters and return 1, 0 or -1 as the result of comparison; its filter() method can take a function reference which takes one parameter and returns true or false. The following example shows how to do a custom sorting on array elements.

Listing 6.13 custom_sort
a = [ '1.2', '3', '3.9', '1.10', '1.2.1', '2.3', '3' ];
a.sort( &my_comparator );
for x in al { println x; }

function my_comparator(lhs, rhs) {
  la = lhs.csv('.');
  ra = rhs.csv('.');
  for i from 0 to la.size() {
    if la[i].int() < ra[i].int() { return -1; }
    if la[i].int() > ra[i].int() { return 1; }
  }
  if la.size() == ra.size() { return 0; }
  return la.size() > ra.size();
}

This program prints the array list as book section numbers. The result is:

1.2
1.2.1
1.10
2.3
3
3
3.9

Another good example is the toCsv() of the Array object. The following code converts an array of values into comma-separated, quoted strings, which can be used in SQL's where clause as the values for the in expression:

last_names = [ 'Olajuwon', 'Yao' ];
in_expr = last_names.toCsv(',', function(x){ return "'"+x+"'"; });
exeucteQuery qry:
  SELECT * FROM emp WHERE last_name IN ( (* in_expr *) )
;

The resultant SQL statement is:

SELECT * FROM emp WHERE last_name IN ( 'Olajuwon', 'Yao' )

The SQL scripting is introduced in chapter 22. JDBC (SQL) Scripting.


Anonymous Functions

With function variables, functions do not always need names. Anonymous functions can be declared without names; in this case, parentheses around parameters are required, and it must be assigned to a location.

Listing 6.14 filter.judo
a = [ 'a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefg' ];
f = function(elem){ return elem.length() >= 5; };
a.filter(f,true);
println a;

In the filter() call, the first parameter is a filter function. The second parameter of true indicates the filtering is done locally; if false, a new array is returned with the filtered elements. The filtering is for strings over 5-character long. The result is:

[abcde,abcdef,abcdefg]

Function Alias for Java Static Methods

Another way to make new functions is to alias Java class static methods. Aliasing Java static methods is also discussed in Alias Java Static Methods as Functions. The syntax is:

FunctionAlias ::= functionIDENTIFIERforjava::JavaClassName [ () ] ;

Once a Java static method is aliased to be a function, that function can be used almost like a native Judo function:

function now for java::System.currentTimeMillis();
function loadLibrary for java::System.loadLibrary();

millis = now();
loadLibrary("native.dll");

Because the function aliases are indeed Java methods, the method parameters are fixed and strongly typed. You have to pass exactly the same number of parameters, and the parameter values should be compatible with the declared parameter types, and sometimes explicit casting may be needed. See Alias Java Static Methods as Functions for more details.


System Functions

Judo has a number of system functions for various purposes. They are actually the methods of an internal $$sys object but $$sys is not required to use them. This is called method shortcut. In addition to $$sys, shortcut methods also exists for internal object $$con (the default database connection). In Judo, values and objects all have methods. The mathematical functions, for instance, are methods of numeric values. System functions are those that do not belong to any objects but useful system-wide.

The system functions fall into the following categories: values and numbers, system properties and related, system controls, system standard input-output, file input-output and generic. Refer to appendix 3. Built-In System Functions for a complete listing.



 
Exception Handling

Judo can catch runtime exceptions, either from the language engine or from Java. The try-catch-finally syntax has two equivalent forms:

BlockCatchFinally ::= { ( Statement )+ [ catch [ IDENTIFIER ] : ( Statement )+ ] [ finally : ( Statement )+ ] }
TryCatchFinally ::= try Block [ catch [ IDENTIFIER ] Block ] [ finally Block ]

In the second form, at least one of catch and finally clauses must appear. The following is an example:

try {
  xxxxx(); // doesn't exist and will fail.
} catch ex {
  println 'Catch: ', ex;
} finally {
  println 'Finally.';
}

The first form is compact and easy; the second form is more Java-like and elegant but verbose. The choice is totally up to your style. The block form can also be applied to bodies of functions and compound statements. Note that if-else and switch statements' blocks can not have catch and finally clauses, as these blocks are just syntactic blocks and not block statements.

The catch clause can take a variable name to hold the exception object; if not specified, $_ is used, as is the case in the following example:

{
  xxxxx(); // doesn't exist and will fail.
catch:
  println 'Catch: ', $_;
finally:
  println 'Finally.';
}

In the global scope, you can have one catch and one finally clauses:

xxxxx(); // doesn't exist and will fail.

catch:   println 'Catch: ', $_;
finally: cleanup();

The Exception Object

The exception object in the catch clause is a built-in object. For Java exceptions, the exception object wraps the Java exception, and all the Java exception methods can be accessed. The Judo exception object has these properties:

Table 6.1 Exception Object Property
NameDescription
linethe line number in the script where the exception happened.
filethe file name of the script in which the exception happened.
messagethe message for the exception.
namethe internal name of the exception.
typethe internal type of the exception.

The most frequently used properties are line and message.

The Throw and Resume Statements

The throw and resume statements are two exception-related statements in Judo. The throw statement throws an exception that transfers the control to the immediate catch clause, or it aborts the program. Its syntax is:

Throw ::= throw [ Expr ] ;

The Expr should be evaluated to be either an exception object (including Java exception object) or a string. If a string or no value is specified, a USER_EXCEPTION is thrown.

The resume statement is used only during handling exception in the catch clause. It resumes the execution after where the exception has happened. If it has no effect if it appears in non-catch code. It takes no parameters:

Resume ::= resume ;

The following test demonstrates most of the exeption handling topics, including the exception object properties, throw and resume statements, and catch and finally in local and global scopes.

Listing 6.15 excpt_test.judo
{
  xxxxx();  // method does not exist
  println 'Not reached.';
catch:
  println '[Line ', $_.line, '] INSIDE CATCH: <',
          $_.name, '> ', $_.message;
  throw $_;
finally:
  println 'INSIDE FINALLY.';
}

throw;
throw new java::Exception("This exception is pure Java.");
throw "ABCDE";

catch:
  println '[Line ', $_.line, '] OUTSIDE CATCH: <',
          $_.name, '> ', $_.message;
  resume;

The output is:

[Line 2] INSIDE CATCH: <METHOD_NOT_FOUND> Function xxxxx() not found.
INSIDE FINALLY.
[Line 2] OUTSIDE CATCH: <METHOD_NOT_FOUND> Function xxxxx() not found.
[Line 12] OUTSIDE CATCH: <USER_EXCEPTION>
[Line 13] OUTSIDE CATCH: <JAVA_EXCEPTION> This exception is pure Java.
[Line 14] OUTSIDE CATCH: <USER_EXCEPTION> ABCDE

The catch and finally clauses do not create new scopes; that is, they are all in the same scope as the whole block. In the format of try { .. } catch { .. } finally { .. }, this may not be obvious.


 
back to top
 



Copyright © 2001-2005 JudoScript.COM. All Rights Reserved.