JudoScript.COM Design principles of Judo the sport and the language
HomeJudo LanguageJuSP PlatformJamaica Language 
Judo ReferenceJuSP ReferenceWiki/WeblogTutorials/PresentationsDownloadsGoodiesFeedback  
Article: Functions, Classes, Threads and Eval
 








This article is old and is being consolidated into the book.
Please refer to the corresponding chapter(s) therein.
If the chapters or sections are not completed yet, you can use this article.
Refer to the examples as they are tested against the latest code.

Table Of Content

  1. User-Defined Functions
    » Parameters
    » Function Variables
    » Lambda
    » Aliases for Java Static Methods
  2. System Functions
  3. User-Defined Classes
    » Class Transposition
  4. Variable Scope
  5. Threads
  6. Dynamic Programming
  7. Summary
  8. Code Listings

Functions, Classes, Threads and Eval

By James Jianbo Huang    October 2001  UPDATED: July 2003     printer-friendly version

Abstract   This article discusses user functions, classes, threads and dynamic evaluation. Variable scope is an important topic and many things are cleared here. JudoScript supports lambda functions, or anonymous functions, and function variables; these are useful for, say, array sorting and filtering. Also supported is aliasing for Java class static methods. System functions are generally discussed. JudoScript threads are declared like functions and started with start thread. Dynamically created code can be evaluated either locally with eval or separately with evalExternal and evalFile.


 

1. User-Defined Functions

The syntax for function declaration is:

function fxn_name [ ( ] params [ ) ] { statements }
The parentheses around parameters are not required. Functions always return a value, either a null or a value issued in a return statement. Parameter names are the same as variable names. A function is invoked by its name with parameter values. The following is the famous Hanoi Tower problem followed by the result of a test run. Note that functions can be declared anywhere, because a script is parsed and all declarations are collected before any runs.

Listing 1. hanoi.judo
1: cnt = 0;
2: hanoiTower(4, 'A', 'B', 'C');
3:
4: function hanoiTower N, src, aux, dst {
5:   if N == 0 { return; }
6:   hanoiTower(N-1, src, dst, aux);
7:   println 'step ', ++cnt : > 2, ':  ', src, ' => ', dst;
8:   hanoiTower(N-1, aux, src, dst);
9: }

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

Parameters

Function parameters may take default values. In fact, a function name is unique, and functions can be called with any number of parameters regardless of those specified in the declaration. If fewer parameter values are supplied than as declared, the default values are used; if not default values, null is used. What happens if more values than declared parameters? Those extra values are stored in an internal array variable, $$args. To explicitly declare that a function takes variable number of parameters, you may end the parameter list with two dots (".."):

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 'param: ', a;
  if $$args != null {
    println $$args.length, ' useless parameters.';
  }
}
oneparam('abc');
oneparam('abc', x, y, z);
The dot command is a shortcut for println, real short.

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.

function foo x, y { return x+y; }
a = &foo;
println a->(1,2);

Listing 2. fxn_var.judo
1: function foo1 a, b { return a + b; }
2: function foo2 a, b { return a * b; }
3: function whichFoo f, a, b { return f->(a,b); }
4:
5: println 'whichFoo(&foo1,2,3) = ', whichFoo(&foo1,2,3);
6: println 'whichFoo(&foo2,2,3) = ', whichFoo(&foo2,2,3);

JudoScript supports array sorting, filtering and element-wise conversion. They all take function variables as parameters. For instance, array sorting take a function that should take two parameters and return 1, 0 or -1 as the result of comparison.

Listing 3. custom_sort.judo
 1: a = [ '1.2', '3', '3.9', '1.10', '1.2.1', '2.3', '3' ];
 2: a.sort( &my_comparator );
 3: for i from 0 to a.lastIndex() { println i, '  ', a[i]; }
 4:
 5: function my_comparator(lhs, rhs) {
 6:   la = lhs.csv('.');
 7:   ra = rhs.csv('.');
 8:   for i from 0 to la.size() {
 9:     if la[i].int() < ra[i].int() { return -1; }
10:     if la[i].int() > ra[i].int() { return 1; }
11:   }
12:   if la.size() == ra.size() { return 0; }
13:   return la.size() > ra.size();
14: }

Lines 5 through 14 defines a custom comparator. On line 1, we have an array of something that looks like book sections. Normal string comparison fails to yield correct order. Our comparator takes apart the section number to an array (lines 6 and 7), and compares each parts. The result is:

0  1.2
1  1.2.1
2  1.10
3  2.3
4  3
5  3
6  3.9

Lambda

With function variables, functions do not always need names. Anonymous functions are called lambda functions.

a = [ 'a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefg' ];
f = lambda elem { return elem.length() >= 5; };
a.filter(f,true);
println a;
In the filter() call, the second parameter of true indicates the filtering is done locally. The first parameter is a lambda as a filter function.

Aliases for Java Static Methods

Java class static methods can be aliased to appear like regular JudoScript functions.

function currentTimeMillis for javaclass java.lang.System.currentTimeMillis();
function loadLibrary for javaclass java.lang.System.loadLibrary();

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

Review Questions

  • How to declare a function?
  • Can functions call themselves?
  • If a function is invoked with more parameters than declared, how to get the extra ones?
  • If a function is invoked with less parameters than declared, what happens?
  • How to assign a function to a variable? How to invoke that function variable? Can it be passed to a function?
  • How to create an anonymous function?
  • What is a comparator function? What is its requirements? What is a filter function? Can you guess its requirements?
  • How to declare a function to be an alias to a Java class static method?

 

»»» Top |  This Section «««

 

2. System Functions

JudoScript 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 these internal objects: $$con (database connection) and $$timer (scheduler timer). In JudoScript, values and objects all have methods. The mathematical functions, for instance, are methods of numeric values. System functions (or, rather, methods), 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. See language specification for a complete listing. These functions are discussed in detail in respective topics; they are briefly listed below.

Value and number functions:

date [ year [ , month [ , day [ , hour [ , minute [ , second ] ] ] ] ] ]
time hour [ , minute [ , second ] ]
timeToday hour [ , minute [ , second ] ]
rand|random [ lower , ] upper
unit count, singular [ , plural ]
compare left, right

System properties and related functions:

systemProperty name [ , defaultVal ]
systemProperties
osName
isMac
isWindows
isHPUX
isLinux
isSunOS
javaVendor
userName
homeDir
curDir|pwd

System control functions:

exit [ returnVal ]
sleep [ duration ]
lock lockname
unlock lockname
waitFor signalname
notify signalname
notifyAll signalname

System standard input-output:

getOut
getErr
getLog
setOut printwriter
setErr printwriter
setLog printwriter

File input-output functions:

openFile filename [ , mode ]
openTextFile filename [ , mode ]
openRandomAccessFile filename [ , mode ]
openGZippedFile filename [ , mode ]
openGZippedTextFile filename [ , mode ]
openZip zipfilename
createZip zipfilename
createJar zipfilename [ , manifest ]
getFileContent filename
getGZippedFileContent gzipfilename

Generic functions:

setHttpProxy server , port
timerHandler
setGuiListener component , eventhandlername
connectMailServer server [ , username [ , password ] ]
disconnectMailServer
getInitialContext|initialContext factoryname , url [ , username [ , password ] ]
getWeblogicContext|weblogicContext url [ , username [ , password ] ]

Review Questions

  • What is "method shortcut"?
  • How to easily print out "I have 1 apple." or "I have 3 apples"?
  • How to get the home directory?
  • How to save logged information to a file of your choice?
  • How to platform-specific tasks, such as loading native libraries?

 

»»» Top |  This Section «««

 

3. User-Defined Classes

JudoScript supports user-defined classes. A JudoScript class is just a struct with user-defined methods. All struct operations are available to user-defined classes. See the other article for how to use structs. All the members (or attributes) are accessible; there is no accesss control such as "private" or "protected". A class instance is initialized just like an Object except the class name is used instead of "Object":

a = new MyClass( alfa=1, beta='abc' );
println a.alfa, ' ', a.beta;
Classes can have constructors; they do not take any parameters, and are invoked after the object is initialized. Because data members are not declared, it is good practice to document them in the comment preceding or withing the class. The following example defines a Node class and constructs a tree for traversals.

Listing 4. dfs_bfs.judo
 1: class Node
 2: {
 3:   constructor {
 4:     assert(name != null);  // mandates that 'name' is initialized
 5:     children = [];
 6:   }
 7:   function addChild child { children.add(child); }
 8:   function toString { return name; }
 9: }
10:
11: // constuct a tree
12: root = new Node(name='ROOT');
13: a = new Node( name='A' );
14: a.addChild(new Node(name='A1'));
15: a.addChild(new Node(name='A2'));
16: root.addChild(a);               // left subtree
17: a = new Node( name='B');
18: a.addChild(new Node(name='B1'));
19: a.addChild(new Node(name='B2'));
20: a.addChild(new Node(name='B3'));
21: root.addChild(a);               // right subtree
22:
23: dfs(root);
24: bfs(root);
25:
26: function dfs root {
27:   print 'Depth-first traverse: ';
28:   $stack = new stack;
29:   $stack.push(root);
30:   while !$stack.isEmpty() {
31:     node = $stack.pop();
32:     print node, ' ';
33:     for x in node.children backward { $stack.push(x); }
34:   }
35:   println;
36: }
37:
38: function bfs root {
39:   print 'Breadth-first traverse: ';
40:   $queue = new queue;
41:   $queue.enq(root);
42:   while !$queue.isEmpty() {
43:     node = $queue.deq();
44:     print node, ' ';
45:     for x in $node.children { $queue.enq(x); }
46:   }
47:   println;
48: }

Class Node has two attributes: "name" and "children". In the constructor, lines 4 mandates that an attributed called "name" must be initialized, and line 5 creates the attribute "children" as an array. The class defines a method calld addChild. It also defines a toString() method; when this is defined, the println statement prints whatever it returns.

A class can extend another. For methods, since parameters have no types and any number of parameters are allowed, each method must be unique. When a class is extended, that method may be overridden. To invoke a parent's method. use the super qualifier.

Listing 5. john_son.judo
 1: class John
 2: {
 3:   constructor {
 4:     println "I love my baseball club.";
 5:   }
 6:
 7:   function plays {
 8:     return new array( 'baseball' );
 9:   }
10: }
11:
12: class Johnson extends John
13: {
14:   constructor {
15:     println "I always bring my tennis racket.";
16:   }
17:
18:   function plays {
19:     arr = super.plays();
20:     arr.add('basketball', 'tennis', 'soccer', 'gymnastics', 'piano' );
21:     return arr;
22:   }
23: }
24:
25: println (new Johnson).plays();

The method plays() is overridden in the child class; it calls the parent's version to get an array of what his dad is up to, addes his own and returns the array. The constructors of both classes print out a message. The parent classes' constructors are run first. The result is:

I love my baseball bat.
I always bring my tennis racket.
[baseball,basketball,tennis,soccer,gymnastics,piano]
In the methods, own methods can be invoked without any qualifiers; in other words, own method names take precedence over global function names. To access own's own attributes, use get() method or the this.() notion.

Classes without a parent conceptually extend struct. You can make a class extend ordered map.

class MyClass extends orderedMap
{
  constructor { alfa=1, beta=2, gamma=3 }
  function printAll {
    for x in keys() { println x, ' => ', this.(x); }
  }
}

Class Transposition

Instances of a class can be converted to another class on-the-fly by the built-in method transpose(). This is typically used when a struct, orderedMap or class is returned from some functions and methods (especially the built-in ones), and later a new class with more and newer methods is intended to act upon it. As we know, a class is nothing but a collection of dynamic data members, transposing a class to another is essentially re-associating the data with a new set of methods, except that structs can not be cast to orderedMaps because the latter has mechanisms that the former lacks.

The following program calls the string method parseUrl() which returns a struct of various information; on lines 26 through 34, a custom class, UrlInfo, is defined with a toString() method (lines 28 through 33) that reconstructs the URL. It is used on line 23 to convert the struct into a UrlInfo, and calles its toString() method implicitly.

Listing 6. parse_url.judo
 1: a = ['http://localhost:8080/articles/developer.html#top',
 2:       'http://localhost/cgi-bin/check.pl?id=1234&sess=abc',
 3:       '/index.html',
 4:       'index.html',
 5:       '',
 6:       '/',
 7:       'http://www.judoscript.com',
 8:       'images/bg.gif'
 9:      ];
10: for url in a {
11:   b = url.parseUrl();
12:   println '-----------------------------------------------';
13:   println '            URL: ', url;
14:   println '           root: ', b.root;
15:   println '       protocol: ', b.protocol;
16:   println '         domain: ', b.domain;
17:   println '           host: ', b.host;
18:   println '           port: ', b.port;
19:   println '           path: ', b.path;
20:   println '      file_name: ', b.file_name;
21:   println '   query_string: ', b.query_string;
22:   println '            ref: ', b.ref;
23:   println 'constructed URL: ', b.transpose('UrlInfo');
24: }
25:
26: class UrlInfo
27: {
28:   function toString() {
29:     ret = root @ path;
30:     if query_string != null { ret @= '?' @ query_string; }
31:     if ref != null { ret @= '#' @ ref; }
32:     return ret;
33:   }
34: }

Review Questions

  • Define a class called Order that have an attribute "createTime" defaulted to now and "amount" defaulted to 0.
  • The Order class requires attribute "name" be initialized to a non-empty string. How to enforce this?
  • A class is just a struct. User can attach more and more attributes. How to list all the attributes at a particular moment?
  • When a class is extended, when is the parent class's constructor called?
  • The this reference is avaiable in a method. Can you think of its uses?
  • An object is of a user-defined class which extends orderedMap. When it is being converted to another class which extends struct via a transpose() call, what happens? And vice versa?

 

»»» Top |  This Section «««

 

4. Variable Scope

First of all, let us clear some terminology. A function in the global scope is called a function; a function defined within a class is called a method. A pair of curly braces that enclose 0 or more statements is called block; blocks can be enclosed in other blocks. The curly braces for a class does not constitute a block because they never enclose statements. A variable name starts with a dollar sign; a name without a leading dollar sign is a class data member (or attribute).

A context is where variables reside. When a program starts, it is in a root or global context. In most cases, a block is equivalent to a context, for instance, a function, a thread, a loop statement like for and while, a try-catcn-finally block, and anonymous blocks. The only exceptions are the blocks in if-else and switch statements, because such simple braching does not deserve a separate context yet syntactically they do have blocks.

When a variable is referenced, the JudoScript engine starts searching from the current context up the block chain, until either the variable is found in one of the context, or a "terminal" context is reached, in which case a null is returned. A terminal context is that of a method or the global context itself. Global functions are considered child contexts of the global one. You can force to access a global variable (variables in the global context) from any code by preceding the variable name with the :: decorator. Constants are always global.

When a variable is being assigned a value, the same search process occurs; if found, the value is set for the variable in that context. If not, a new variable is created in the current context. A local variable can be created in the current context by the decorator local in front of the assignment, so that an variables with the same name in parent contexts are not accessed and affected.

Class members are, strictly speaking, not variables. They can be referenced and assigned values, and are always in the class instance.

The following is a boring example that simply experiments with scopes:

Listing 7. var_scope.judo
 1: println "global a = ", a = 1;
 2: {
 3:   local a = 2;
 4:   println "local a = ", a;
 5:   println "::a = ", ::a;
 6: }
 7: println 'global a = ', a;
 8:
 9: class MyCls
10: {
11:   function foo {
12:     println "in class: a = ", a;
13:     local a = 2;
14:     println "in class: local a = ", a;
15:     println "in class: ::a = ", ::a;
16:   }
17: }
18: (new MyCls).foo();

The result is:

global a = 1
local a = 2
::a = 1
global a = 1
in class: a =
in class: local a = 2
in class: ::a = 1

Review Questions

  • What is the difference between a function and a method in terms of variable scope?
  • When a variable is not defined anywhere yet, where will it be created by an assignment?
  • What will be printed in the following program? If the first line is uncommented, then what?
    //x = 9;
    for x from 0 to 5 {
    }
    println x;
    
  • In the following
    for x in array {}
    
    is x local? (Judge by common sense.)
  • How to defined a local variable? Why you may need to do so?
  • How to access a global variable and constant from a class method?

 

»»» Top |  This Section «««

 

5. Threads

A JudoScript thread is defined exactly the same as a function except the keyword is thread instead of function. It can take parameters optionally with default values. Threads do not, however, return any values. Threads are global objects; they can not be declared within a class. To start a thread, use the start thread or start daemon thread command.

thread myFirstThread millis {
  for i from 1 to 10 {
    sleep(millis);
    println "Hah!";
  }
}
start thread myFirstThread(1000);
Or you can start an anonymous thread without declaration:
start thread millis = 1000 {
  for i from 1 to 10 {
    sleep(millis);
    println "Hah!";
  }
}
The parameters in this case are for code clean-ness. They should all be initialized.

Threads are run in their own contexts, a child to the root context. The parameters are evaluated in the current context and their values are stored in the new thread context.

Threads run with others; coordination of accesses to variables is essential to thread programming. There are two ways to share variables among threads: global variables and non-primitive parameters. If two threads happen to modify a same shared object at the same time, the result will be unpredicted. To ensure ownership of a shared object, use system functions lock() and unlock() to serialize accesses.

Listing 8. locks.judo
 1: const #fmt = 'mm:ss.SSS'; // minute:second.millisecond
 2:
 3: thread t name, dur = 2000 {
 4:   while {
 5:     sleep(dur);
 6:     lock 'house';
 7:     println name, ' have it!  ', date().fmtDate(#fmt);
 8:     sleep(dur);
 9:     println name, ' give up.  ', date().fmtDate(#fmt);
10:     unlock 'house';
11:   }
12: }
13:
14:
15: start thread t('Kitty', 1000);
16: sleep(1300);
17: start thread t('Doggy');

In this program, a lock named "house" is used to serialize execution. When one thread owns the lock, others trying to lock it are blocked until that owner thread unlocks. The result is listed below; look at the time of the events, Doggy holds the lock for 2 second and Kitty holds for 1 second. When one releases the lock, the other grabs it immediately.

Kitty have it!  58:15.706
Kitty give up.  58:16.707
Kitty have it!  58:17.709
Kitty give up.  58:18.710
Doggy have it!  58:18.710
Doggy give up.  58:20.713
Kitty have it!  58:20.713
Kitty give up.  58:21.714
Doggy have it!  58:22.716
Doggy give up.  58:24.719
Kitty have it!  58:24.719
......
To synchronize threads, the system function waitFor(), notify() and notifyAll() can be used. These functions work on a signal name. The following program is a classic producer-consumer problem. The consumer thread waits for the goods produced by the producer; if no goods available, it go to sleep until somebody (typically the producer) wakes it up. The producer thread periodically produces a random number of goods.

Listing 9. producer_consumer.judo
 1: inventory = 0; // shared
 2:
 3: thread consumer
 4: {
 5:   while inventory <= 0 {
 6:     waitFor 'has-goods';
 7:
 8:     lock 'use-goods';
 9:     for x from 1 to inventory { print '* '; }
10:     println;
11:     inventory = 0;
12:     unlock 'use-goods';
13:   }
14: }
15:
16: thread producer
17: {
18:   while {
19:     sleep 1000;
20:     lock 'use-goods';
21:     if inventory == 0 { inventory = random(5,10); }
22:     unlock 'use-goods';
23:
24:     notifyAll 'has-goods';
25:   }
26: }
27:
28: start thread consumer;
29: start thread producer;

In the consumer thread, lines 8 and 12 guarantee ownership of the global variable inventory, as do lines 20 and 22 in the producer thread. The producer wakes up all the waiting consumer threads on line 24 when the inventory is beyond 0.

Review Questions

  • How to declare a thread? Can you declare it in a class?
  • How to start a thread? Can you start it from a method?
  • Do you have to acquire a lock to access and modify a global variable in a thread?
  • The main program runs in the default main thread. Can you share global variables with threads? If so, is serialized accesses necessary?
  • How to synchronized threads with waitFor(), notify() and notifyAll()? Can you use locks to do so?

 

»»» Top |  This Section «««

 

6. Dynamic Programming

You can dynamically create JudoScript code and run, either in the current runtime context with eval command or in a separate context with evalExternal and evalFile. evalFile takes a file name instead of code.

eval '. "ABCDEFG"';
When the dynamic code is evaluated with eval, the declarations such as functions, classes and constants are taken into the current runtime context. evalExternal and evalFile do not.
eval [[*
  const #acon = 'a';
  function foo() { println 'From foo()'; }
  class BarCls { constructor { println 'BarCls.ctor()'; } }
*]];

println '#acon = ', #acon;
foo();
new BarCls;

evalExternal and evalFile can take parameters using the with clause:

code = [[*
  if #args.length < 0 {
    println  'Usage: java judo ', #prog, ' x';
    exit 0;
  }

  println 'The argument is: ', #args[0];
*]];
evalExternal code;
evalExternal code with 'abcd';
The result is:
Usage: java judo  x
The argument is: abcd

The following is an example. Last July, Rainbow Inc., a retail company, ramped up its e-commerce presence. This July, Mr. Smart is hired to head the marketing department. He devised a sophisticated pricing scheme to promote certain products. Fortunately, the consultants who designed the system used JudoScript's dynamic evaluation feature, so Mr. Smart's unforeseeable request is entered into the system without any code rewrite.

Listing 10. new_princing.judo
 1: // pre-Mr.Smart pricing -- flat
 2: pricing = lambda prod, quantity {
 3:              switch prod {
 4:              case 'candy': return 1.49 * quantity;
 5:              case 'chips': return 2.49 * quantity;
 6:              case 'beer':  return 2.99 * quantity;
 7:              default:      return 0.99 * quantity;
 8:              }
 9:            };
10:
11: println '10 candies: ', pricing('candy', 10);
12:
13: // post-Mr.Smart pricing -- quantity discount
14: eval [[[*
15:   pricing = lambda prod, quantity {
16:                switch prod {
17:                case 'candy': unitprice = 1.49; break;
18:                case 'chips': unitprice = 2.49; break;
19:                case 'beer':  unitprice = 2.99; break;
20:                default:      unitprice = 0.99; break;
21:                }
22:                if quantity <= 5 {
23:                  return unitprice * quantity;
24:                } elif quantity <= 10 {
25:                  return (unitprice * 0.95 * quantity).fractionDigits(2);
26:                } else {
27:                  return (unitprice * 0.90 * quantity).fractionDigits(2);
28:                }
29:              };
30: *]];
31:
32: println ' 5 candies: ', pricing('candy', 5);
33: println '10 candies: ', pricing('candy', 10);
34: println '15 candies: ', pricing('candy', 15);

What happens is, the software has a admin-tool that allows a human operator to type in the new pricing scheme (lines 15 through 29) and submit to the system, test out and commit the changes.

Review Questions

  • Think of a situation where functions are dynamically created and used.
  • How to run dynamically generated code without affecting the current runtime context?

 

»»» Top |  This Section «««

 

7. Summary

User functions and class methods are declared with a name and 0 or more parameters, with or without default values. A function or method can be invoked with differnt number of parameters than what is declared. When fewer parameters present, null is used for the missing parameters; if more parameters than declared are passed, the extra ones are in the array $$args. Functions can be recusrively called. Functions can be assigned to variables by the & operator. Lambda functions are anonymous functions. Function variables are useful for array sorting, filtering, element-wise conversion and any dynamic programming. Java class static methods can be aliased and be used like a regular JudoScript function.

JudoScript supports a set of system functions; they are actually the methods of a built-in object, $$sys. These functions can be called directly via a mechanism called function shortcut. Most of the system functions are listed in categories without much explanation.

User classes are extensions to struct or ordered map. They typically have methods. Method toString() is special; when defined, is used by the print statements. Classes may have a constructor, which takes no parameters. It is called after the class object is initialized. Use new operator to create a class instance, with named initializers for the the class members or attributes. In the constructor, you can ensure certain members are initialized by calling assert(somefield != null);. Classes can singly extend others. Parent classes' constructors are called first. In the class methods, the special variable this to pass itself to other methods, and super to invoke the immediate parent's same-name methods.

Variables belong to a context, normally equivalent to a block in the code; the only exceptions are blocks of if-elif-else and switch statements. New variables are created in the current context when there are no variable with that name exist in the context chain. Global functions use the global context as its parent context; class methods have no parent context. The decorator :: in front of a variable name explicit accesss a global variable. To explicitly define a variable in the current context, use the local decorator; same-namevariables in the parent contexts are shielded and not accessible except for explict global accesses.

Threads are defined just like a function in JudoScript except the keyword thread replaces function. They are started via the start thread command. Anonymous threads can be started directly. Threads are global objects. The ways to share information is either by global variables or parameters of compound data structures. To synchronize threads and serialize access to shared object, use the system functions lock(), unlock(), waitFor(), notify() and notifyAll().

JudoScript code can be dynamically generated and evaluated by eval and evalExternal commands. The eval command evaluates the code locally; declarations in the code are taken and kept. evalExternal evaluates in a separate runtime context.

 

»»» Top |  This Section «««

 

8. Code Listings

  1. hanoi.judo
  2. fxn_var.judo
  3. custom_sort.judo
  4. dfs_bfs.judo
  5. john_son.judo
  6. parse_url.judo
  7. var_scope.judo
  8. locks.judo
  9. producer_consumer.judo
  10. new_princing.judo




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