The JavaFX Script Programming Language
Last Updated: May 2007
The JavaFX Script™ (hereinafter referred to as JavaFX) language is a declarative and statically typed programming language. It has first-class functions, declarative syntax, list-comprehensions, and incremental dependency-based evaluation. The JavaFX Script language makes intensive use of the Java2D swing GUI components and allows for easy creation of GUIs.
This document gives an informal description of the JavaFX Script programming language.
Contents:
Basic Types
Calling Java Objects
Variables
Functions, Arrays, Expressions, and Operations
Modifying Arrays
Insert Statement
into
before, after
Delete Statement
Querying Arrays
Expressions
String Literals and String Expressions
Quoted Identifiers
Range Expression
String, Number and Date Formatting
Operations
Expression Statement
If Statement
While Statement
Try Statement
For Statement
Return Statement
Throw Statement
Break and Continue Statements
Do Statement
do later
Classes and Objects
Attribute Declarations
Object Literals
Update Triggers
Creation Triggers
Insert Triggers
Delete Triggers
Replace Triggers
Incremental and Lazy Evaluation
Reflection
Extents and Enumerations
top
Basic Types
The JavaFX programming language provides four primitive types: String, Boolean, Number, and Integer. These types correspond to Java types as follows:
JavaFX Java
String java.lang.String
Boolean java.lang.Boolean
Number java.lang.Number
Integer byte,short,int,long,BigInteger
Example:
var s = "Hello";
s.toUpperCase(); // yields "HELLO";
s.substring(1); // yields "ello";
var n = 1.5;
n.intValue(); // yields 1
(1.5).intValue(); // yields 1
s.substring(n); // yields "ello"
var b = true;
b instanceof Boolean; // yields true
Coercions are automatically performed on numeric types when passing arguments or return values to/from Java methods. In addition, implicit truncating coercions are performed when converting Numbers to Integers.
top
Calling Java Objects
JavaFX programs can import Java classes, create new Java objects, call their methods, and implement Java interfaces. The following code snippet provides an example:
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.lang.System;
var frame = new JFrame();
var button = new JButton("Press me"

;
frame.getContentPane().add(button);
button.addActionListener(new ActionListener() {
operation actionPerformed(event) {
System.out.println("You pressed me"

;
}
});
frame.pack();
frame.setVisible(true);
Running the above program displays the following on the screen:
Of course, this isn't the preferred way of creating GUI's in JavaFX. The following JavaFX code achieves the same effect:
Frame {
content: Button {
text: "Press Me"
action: operation() {
System.out.println("You pressed me"

;
}
}
visible: true
}
top
Variables
In JavaFX, the var keyword introduces a new variable. You may specify the type of a variable in its declaration. However, that's optional in JavaFX. If you don't specify the type, the JavaFX interpreter infers the variable's type from its use. A variable declaration takes the form
var variableName : typeName [?,+,*] = initializer;
You may use one of the ?, +, or * operators to denote the cardinality of the variable, as follows:
Operator Meaning
? Optional (i.e, may be null)
+ One or more
* Zero or more
Example:
var nums:Number* = [1,2,3];
The above example declares a new variable named nums whose value is defined to consist of zero or more instances of type Number and whose initial value is [1,2,3].
The :typeName, [?,+,*], and = initializer portions of the declaration are optional, so the following is equivalent to the above: var nums = [1,2,3];
top
Functions, Arrays, Expressions, and Operations
JavaFX functions represent a pure functional subset of the JavaFX programming language. The body of a function may only contain a series of variable declarations and a return statement. JavaFX also provides procedures (called operations, see below) which may contain any number of statements including conditional statements, looping statements, try/catch, etc. The order in which the functions are given is not in general significant. Following is a very simple example of a functional program:
function z(a,b) {
var x = a + b;
var y = a - b;
return sq(x) / sq (y);
}
function sq(n) {return n * n;}
function main() {
return z(5, 10);
}
There are no mandatory type declarations, although the language is statically typed (see more details later).
The most commonly used data structure is the array, which in JavaFX is written with square brackets and commas, e.g.: var week_days = ["Mon","Tue","Wed","Thur","Fri"];
var days = [week_days, ["Sat","Sun"]];
Arrays represent sequences of objects. In JavaFX arrays are not themselves objects, however, and do not nest. Expressions that produce nested arrays (as in the initialization of "days" above) are automaticallly flattened, i.e:
days == ["Mon","Tue","Wed","Thur","Fri","Sat","Sun"]; // returns true
The size of an array may be determined with the JavaFX sizeof operator:
var n = sizeof days; // n = 7
There is a shorthand notation using ".." for arrays whose elements form an arithmetic series. Here for example are definitions of the factorial function, and of a number "result" which is the sum of the odd numbers between 1 and 100 function fac(n) {return product([1..n]);}
var result = sum([1,3..100]);
The elements of an array must all be of the same type.
Arrays may be indexed as in Java:
var wednesday = days[2];
In JavaFX the [] operator also expresses selection (similar to its use in XPath). In this case, the expression contained in the [] is a boolean expression. Such an expression returns a new array containing only those elements that satisfy the predicate contained in the [].
As in XPath, within the predicate contained inside the [] operator, the context object may be accessed with the dot operator, for example:
var nums = [1,2,3,4];
var numsGreaterThanTwo = nums[. > 2]; // yields [3, 4]
Alternatively a variable may be declared for the context object. For example, this is equivalent to the above statement:
numsGreaterThanTwo = nums[n|n > 2];
The JavaFX indexof operator returns the ordinal position of an element within an array (like the position() function in XPath).
The car and cdr of a list may be expressed using selection expressions like this:
function car(list) {return list[indexof . == 0];}
function cdr(list) {return list[indexof . > 0];}
Of course car can be expressed more succinctly as simply:
function car(list) {return list[0];}
Examples:
var list = [1..10];
car(list); // yields 1
cdr(list); // yields [2,3,4,5,6,7,8,9,10]
In JavaFX, the empty array [] and null are synonymous, i.e:
[] == null // yields true
sizeof null // yields 0
top
Modifying Arrays
In addition to the assignment operator (=), JavaFX provides data modification operators (insert and delete) similar in syntax and semantics to those in the draft XQuery-Update specification as follows:
Insert Statement
The insert statement can take any of the following forms:
insert Expression1 [as first | as last] into Expression2
insert Expression1 before Expression2
insert Expression1 after Expression2
The insert statement inserts the items returned by evaluating Expression1 into the location indicated by remainder of the statement as follows:
into
Expression2 must refer to an attribute or variable. If Expression2 refers to a single valued attribute then the effect of the insert is the same as if the assignment operator were used.
If as first is specified, the insertion location is before the first element of the list indicated by Expression2. If as last is specified, the insertion location is after the last element of the list indicated by Expression2. If neither as first nor as last is specified explicitly, then as last is used as the default.
Examples:
var x = [1,2,3];
insert 12 into x; // yields [1,2,3,12]
insert 10 as first into x; // yields [10,1,2,3,12]
insert [99,100] as last into x; // yields [10,1,2,3,12,99,100]
before, after
Expression2 must be a selection expression over an attribute or variable. If before is specified, the insertion location is before the selected elements. If after is specified the insertion location is after the selected elements.
Examples:
var x = [1,2,3];
insert 10 after x[. == 10]; // yields [1,2,3,10]
insert 12 before x[1]; // yields [1,12,2,3,10]
insert 13 after x[. == 2]; // yields [1, 12, 2, 13, 3, 10];
top
Delete Statement
The Delete statement takes one of the following forms:
delete variable
delete Expression.attribute
delete variable[predicate]
delete Expression.attribute[predicate]
The first two forms remove all elements from a variable or attribute - which is equivalent to assigning [] or null to the variable or attribute. The latter two forms remove only those elements that match the predicate.
Examples:
var x = [1,2,3];
insert 10 into x; // yields [1,2,3,10]
insert 12 before x[1]; // yields [1,12,2,3,10]
delete x[. == 12]; // yields [1,2,3,10]
delete x[. >= 3]; // yields [1,2]
insert 5 after x[. == 1]; // yields [1,5,2];
insert 13 as first into x; // yields [13, 1, 5, 2];
delete x; // yields []
top
Querying Arrays
JavaFX supports list comprehensions as in functional languages like Miranda and Haskell, but with a familiar syntax that should be easily understood by Java programmers, namely the JavaFX select and foreach operators.
Here is an example:
class Album {
attribute title: String;
attribute artist: String;
attribute tracks: String*;
}
var albums =
[Album {
title: "A Hard Day's Night"
artist: "The Beatles"
tracks:
["A Hard Day's Night",
"I Should Have Known Better",
"If I Fell",
"I'm Happy Just To Dance With You",
"And I Love Her",
"Tell Me Why",
"Can't Buy Me Love",
"Any Time At All",
"I'll Cry Instead",
"Things We Said Today",
"When I Get Home",
"You Can't Do That"]
},
Album {
title: "Circle Of Love"
artist: "Steve Miller Band"
tracks:
["Heart Like A Wheel",
"Get On Home",
"Baby Wanna Dance",
"Circle Of Love",
"Macho City"]
}];
// Get the track numbers of the albums' title tracks
// using the select operator:
var titleTracks =
select indexof track + 1 from album in albums,
track in album.tracks
where track == album.title; // yields [1,4]
// the same expressed using the foreach operator:
titleTracks =
foreach (album in albums,
track in album.tracks
where track == album.title)
indexof track + 1; // also yields [1,4]
A list comprehension consists of one or more input lists, an optional filter and a generator expression. Each source list is associated with a variable. The result of the list comprehension is a new list which is the result of applying the generator to the subset of the cartesian product of the source lists' elements that satisfy the filter.
List comprehensions give a concise syntax for a rather general class of iterations over lists.
Another simple example of a list comprehension is:
select n*n from n in [1..100]
This is a list containing (in order) the squares of all the numbers from 1 to 100. Note that "n" is a local variable of the above expression.
The use of a filter is shown by the following definition of a function which takes a number and returns a list of all its factors,
function factors(n) {
return select i from i in [1..n/2] where n % i == 0;
}
top
Expressions
JavaFX supports the following operators:
Operator Meaning Java Equivalent
Relational Operators
== equality ==
<> inequality !=
< less than <
> greater than >
<= less than or equal <=
>= greater than or equal >=
Boolean Operators
and logical and &&
or logical or ||
not logical negation !
Arithmetic Operators
+ addition +
- subtraction; unary negation -
* multiplication *
/ division /
% remainder %
+= add and assign +=
-= subtract and assign -=
*= multiply and assign *=
/= divide and assign /=
%= remainder and assign %=
Other Operators
sizeof array length n/a
indexof ordinal position n/a
if e1 then e2 else e3 conditional expression e1 ? e2 : e3
select list comprehension n/a
foreach list comprehension n/a
new allocation new
op() function/operation call n/a
x.op() member function/operation call x.op()
instanceof type check instanceof
this self access this
. attribute access, context access ., n/a
bind [lazy] incremental [lazy] evaluation n/a
: eager initialization n/a
[] array selection []
format as String formatting n/a
<<>> Identifier quotes n/a
{} String expression n/a
(expr) grouping (expr)
reverse reverses a list n/a
[number1,next..number2] numeric range n/a
Some Examples:
import java.lang.System;
import java.lang.Math;
var x = 2;
var y = 4;
var a = true;
var b = false;
System.out.println(x == y); // prints false
System.out.println(x <> y); // prints true
System.out.println(x < y); // prints true
System.out.println(x > y); // prints true
System.out.println(x >= y); // prints false
System.out.println(x <= y); // prints true
System.out.println(x + y); // prints 6
System.out.println(x - y); // prints -2
System.out.println(x * y); // prints 8
System.out.println(x / y); // prints 0.5
System.out.println(x % y); // prints 2
System.out.println(a and b); // prints false
System.out.println(a or b); // prints true
System.out.println(not a); // prints false
System.out.println(sizeof [x,y]); // prints 2
System.out.println([x,y][indexof . == 0]); // prints 2
System.out.println(if a then x else y); // prints 2
System.out.println(select q from q in [x, y] where q > 3); prints 4
System.out.println(foreach(q in [x, y] where q < 3) q); prints 2
System.out.println(Math.max(x, y)); // prints 4
System.out.println("abc".toUpperCase()); // prints ABC
System.out.println(x instanceof Number); // prints true
x = 10;
System.out.println(x); // prints 10
top
String Literals and String Expressions
In JavaFX, a literal character string is specified with single quotes, e.g.
var s = 'Hello';
or with double quotes: var s = "Hello";
In the latter case, JavaFX expressions may be embedded using {}, e.g
var name = 'Joe';
var s = "Hello {name}"; // s = 'Hello Joe'
The embedded expression may itself contain quoted strings (which, in turn, may contain further embedded expressions), e.g
var answer = true;
var s = "The answer is {if answer then "Yes" else "No"}"; // s = 'The answer is Yes'
Unlike in Java, JavaFX double-quoted String literals can contain newlines:
var s = "This
contains
new lines";
top
Quoted Identifiers
In JavaFX, any sequence of characters (including whitespace) contained in french quotes <<>> is treated as an identifier. This allows you to use JavaFX keywords (or other normally illegal identifiers) as class, variable, function, or attribute names, e.g.
var <<while>> = 100;
It also makes it possible to call Java methods whose names are the same as JavaFX keywords, for example:
import javax.swing.JTextArea;
var textArea = new JTextArea();
textArea.<<insert>>("Hello", 0);
top
Range Expression
As mentioned above you can define an array of numeric values that form an arithmetic series using the following syntax:
[number1..number2]
Such an expression defines an array whose elements consist of the integers from number1 to number2 (inclusive).
For example:
var nums = [0..3];
System.out.println(nums == [0,1,2,3]); // prints true
By default the interval between the values is 1 but it's also possible to specify a different interval by including the next number in the sequence after number1 separated by a comma. For example, the following expression defines an array consisting of the odd numbers between 1 and 10:
[1,3..10]
If number1 is greater than number2 a descending series is created:
var nums = [3..0];
System.out.println(nums == [3,2,1,0]); // prints true
top
String, Number, and Date Formatting
JavaFX has a built-in String formatting operator (format as), which has the following syntax:
expr format as directive
The format as operator supports java.text.DecimalFormat, java.text.SimpleDateFormat, and java.util.Formatter formatting directives. If the formatting directive starts with %, then java.util.Formatter is used, otherwise if expr is of type Number then java.text.DecimalFormat is used, otherwise if expr is of type java.util.Date then java.text.SimpleDateFormat is used. The directive operand is syntactically an identifier, not an expression. This allows the content of directive to be statically checked for correctness at compile time.
Examples: import java.util.Date;
100.896 format as <<%f>>; // yields '100.896000'
31.intValue() format as <<%02X>>; // yields '1F'
var d = new Date();
d format as <<yyyy-MM-dd'T'HH:mm:ss.SSSZ>>; // yields '2005-10-31T08:04:31.323-0800'
0.00123 format as <<00.###E0>>; // yields '12.3E-4'
top
Operations
In JavaFX, procedures are declared with the operation keyword. For example:
import java.lang.StringIndexOutOfBoundsException;
operation substring(s:String, n:Number): String {
try {
return s.substring(n);
} catch (e:StringIndexOutOfBoundsException) {
throw "sorry, index out of bounds";
}
}
The above example defines a new procedure called "substring" with two arguments, the first named "s" of type "String", the second named "n" of type "Number", returning type "String".
In addition to the assignment, delete, and insert statements mentioned above, the following statements are possible inside the body of an operation :
Expression Statement
A primary expression may be used as a statement, for example:
System.out.println("Hello World!"

;
top
If Statement
The JavaFX if statement is like Java's except that curly braces are always required around the then and else clauses, unless the the else clause is another if statement.
Example:
if (condition1) {
System.out.println("Condition 1"

;
} else if (condition2) {
System.out.println("Condition2"

;
} else {
System.out.println("not Condition 1 or Condition 2"

;
}
top
While Statement
The JavaFX while statement is like Java's except that curly braces are always required around the body.
Example:
var i = 0;
while (i < 10) {
if (i > 5) {
break;
}
System.out.println("i = {i}"

;
i += 1;
}
top
Try Statement
The JavaFX try statement is like Java's but with JavaFX variable declaration syntax. Note: in JavaFX any object can be thrown and caught, not just those that extend java.lang.Throwable.
Example:
try {
throw "Hello";
} catch (s:String) {
System.out.println("caught a String: {s}"

;
} catch (any) {
System.out.println("caught something not a String: {any}"

;
} finally {
System.out.println("finally...");
}
top
For Statement
The header of the JavaFX for statement uses the same syntax as the foreach list comprehension operator. However, in this case the body of the statement is executed for each element generated by the list comprehension.
Examples:
for (i in [0..10]) {
System.out.println("i = {i}");
}
// print only the even numbers using a filter
for (i in [0..10] where i % 2 == 0) {
System.out.println("i = {i}");
}
// print only the odd numbers using a range expression
for (i in [1,3..10]) {
System.out.println("i = {i}");
}
// print the cartesian product
for (i in [0..10], j in [0..10]) {
System.out.println(i);
System.out.println(j);
}
top
Return Statement
The JavaFX return statement is like Java's:
Example:
operation add(x, y) {
return x + y;
}
top
Throw Statement
The JavaFX throw statement is like Java's. However, any object may be thrown, not just those that extend java.lang.Throwable.
Examples:
import java.lang.Exception;
operation foo() {
throw new Exception("this is a java exception");
}
operation bar() {
throw "just a string";
}
top
Break and Continue Statements
The JavaFX break and continue statements are like Java's, however labels are not supported. As in Java, break and continue must appear inside the body of a while or for statement.
Examples:
operation foo() {
for (i in [0..10]) {
if (i > 5) {
break;
}
if (i % 2 == 0) {
continue;
}
System.out.println(i);
}
}
operation bar() {
var i = 0;
while (i < 10) {
if (i > 5) {
break;
}
if (i % 2 == 0) {
continue;
}
System.out.println(i);
i += 1;
}
}
top