Gosu Reference Guide
Gosu Reference Guide
Gosu Reference Guide
This product includes software developed by the Apache Software Foundation (http://www.apache.org).
Contents
About This Document. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Intended Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Downloads, Technical Questions, and Submitting Feedback. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Conventions In This Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1 Gosu Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Welcome to Gosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Control Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Access to Java Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Gosu Classes and Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
List and Array Expansion Operator *. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Case Sensitivity. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Compound Assignment Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Delegating Interface Implementation with Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Gosu Templates. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Native XML and XSD Support. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Native Web Service Support Using a WSDL Type Loader . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Gosu Character Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Running Gosu Programs and Calling Other Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
More About the Gosu Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Compile Time Error Prevention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Type Inference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Intelligent Code Completion and Other Gosu Editor Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Null Safety for Properties Other Operators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Generics in Gosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Gosu Primitives Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Gosu Type Loaders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Gosu Case Sensitivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Gosu Statement Terminators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Gosu Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Gosu Reserved Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Notable Differences Between Gosu and Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Get Ready for Gosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2 Getting Started with Gosu Community Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
System Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Gosu and IntelliJ IDEA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Installing Gosu as Command Line Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Advanced Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Servlet Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Hibernate Database Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Contents 3
Gosu Reference Guide
4 Contents
Gosu Reference Guide
Contents 5
Gosu Reference Guide
Modifiers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Access Modifiers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Override Modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Abstract Modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Final Modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Static Modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Inner Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Named Inner Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Anonymous Inner Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
10 Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Using Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Extracting Information from Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Comparing Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
11 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
What is an Interface? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Defining and Using an Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Defining and Using Properties with Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Modifiers and Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
12 Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Using Gosu Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Overriding Methods Independent of the Delegate Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Declaring Delegate Implementation Type in the Variable Definition . . . . . . . . . . . . . . . . . . 153
Using One Delegate for Multiple Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Using Composition With Built-in Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
13 Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Annotating a Class, Method, Type, or Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Built-in Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Annotations at Run Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Defining Your Own Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Customizing Annotation Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
14 Enhancements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Using Enhancements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Syntax for Using Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Creating a New Enhancement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Syntax for Defining Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Enhancement Naming and Package Conventions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Enhancements on Arrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
15 Gosu Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
What Are Blocks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Basic Block Definition and Invocation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
Variable Scope and Capturing Variables In Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
Argument Type Inference Shortcut In Certain Cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Block Type Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Blocks and Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Blocks as Shortcuts for Anonymous Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
16 Gosu Generics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Gosu Generics Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Using Gosu Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Other Unbounded Generics Wildcards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Generics and Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
6 Contents
Gosu Reference Guide
Contents 7
Gosu Reference Guide
8 Contents
Gosu Reference Guide
25 Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Overview of Thread Safety and Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Gosu Scoping Classes (Pre-scoped Maps) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
Concurrent Lazy Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Concurrent Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
Concurrency with Monitor Locks and Reentrant Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
26 Properties Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Reading Properties Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
27 Coding Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
General Coding Guidelines. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Omit Semicolons. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Type Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
The == and != Operator Recommendations and Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Gosu Case Sensitivity Implications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Class Variable and Class Property Recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Use ‘typeis’ Inference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Contents 9
Gosu Reference Guide
10 Contents
Gosu Reference Guide
This document is a guide for the syntax of Gosu expressions and statements. It also provides examples of how
the syntax can be constructed to write scripts (for example, in rules, libraries, and user interface elements).
Intended Audience
This document is intended for the following readers:
• Programmers who implement and maintain Gosu code
• Implementation team members who configure any part of an application that invokes Gosu.
To ask questions about Gosu or offer general feedback about Gosu, join and post to the Gosu language forum:
http://groups.google.com/group/gosu-lang
To file bug reports, please submit them to the Gosu language bug tracking system:
http://code.google.com/p/gosu-lang/issues/list
Gosu Introduction
This topic introduces the Gosu language, including basic syntax and a list of features.
This topic includes:
• “Welcome to Gosu” on page 13
• “Running Gosu Programs and Calling Other Classes” on page 28
• “More About the Gosu Type System” on page 29
• “Gosu Case Sensitivity” on page 33
• “Gosu Statement Terminators” on page 35
• “Gosu Comments” on page 36
• “Gosu Reserved Words” on page 36
• “Notable Differences Between Gosu and Java” on page 37
• “Get Ready for Gosu” on page 41
Welcome to Gosu
Welcome to the Gosu language. Gosu is a general-purpose programming language built on top of the Java Virtual
Machine. It includes the following features:
• object-oriented
• easy to learn, especially for programmers familiar with Java
• static typing, which helps you find errors at compile time
• imperative
• Java compatible, which means you can use Java types, extend Java types, and implement Java interfaces
• type inference, which greatly simplifies your code while still preserving static typing
• blocks, which are in-line functions that you can pass around as objects. Some languages call these closures or
lambda expressions.
• enhancements, which add functions and properties to other types, even Java types. Gosu includes built-in
enhancements to common Java classes, some of which add features that are unavailable in Java (such as
blocks).
• generics, which abstracts the behavior of a type to work with multiple types of objects. The Gosu generics
implementation is 100% compatible with Java, and adds additional powerful improvements. See “Generics in
Gosu” on page 32 for details.
• native XML/XSD support
• native web service (SOAP) support
• an extensible type system, which means that custom type loaders can dynamically inject types into the
language. You can use these new types as native objects in Gosu. For example, custom type loaders dynami-
cally add Gosu types for objects from XML schemas (XSDs) and from remote WS-I compliant web services
(SOAP). Later versions of the Gosu community release will include more APIs and documentation about
creating your own type loaders.
• large companies around the world use Gosu every day in production systems for critical systems.
Basic Gosu
The following Gosu program outputs the text "Hello World" to the console using the built-in print function:
print("Hello World")
Gosu uses the Java type java.util.String as its native String type to manipulate texts. You can create in-line
String literals just as in Java. In addition, Gosu supports native in-line templates, which simplifies common text
substitution coding patterns. For more information, see “Gosu Templates” on page 26.
To declare a variable in the simplest way, use the var statement followed by the variable name. Typical Gosu
code also initializes the variable using the equals sign followed by any Gosu expression:
var x = 10
var y = x + x
Despite appearances in this example, Gosu is statically typed. All variables have a compile-time type that Gosu
enforces at compile time, even though in this example there is no explicit type declaration. In this example, Gosu
automatically assigns these variables the type int. Gosu infers the type int from the expressions on the right side
of the equals signs on lines that declare the variable. This language feature is called type inference. For more
information about type inference, see “Type Inference” on page 30.
Type inference helps keep Gosu code clean and simple, especially compared to other statically-typed program-
ming languages. This makes typical Gosu code easy to read but retains the power and safety of static typing. For
example, take the common pattern of declaring a variable and instantiating an object.
In Gosu, this looks like:
var c = new MyVeryLongClassName()
As you can see, the Gosu version is easier to read and more concise.
Gosu also supports explicit type declarations of variables during declaration by adding a colon character and a
type name. The type name could be a language primitive, a class name, or interface name. For example:
var x : int = 3
Explicit type declarations are required if you are not initializing the variable on the same statement as the vari-
able declaration. Explicit type declarations are also required for all class variable declarations.
Note: For more information, see “More About the Gosu Type System” on page 29 and “Gosu Classes and
Properties” on page 18.
From the previous examples, you might notice another difference between Gosu and Java: no semicolons or
other line ending characters. Semicolons are unnecessary in nearly every case, and the standard style is to omit
Control Flow
Gosu has all the common control flow structures, including improvements on the Java versions.
Gosu has the familiar if, else if, and else statements:
if( myRecord.Open and myRecord.MyChildList.length > 10 ) {
//some logic
} else if( not myRecord.Open ) {
//some more logic
} else {
//yet more logic
}
Gosu permits the more readable English words for the Boolean operators: and, or, and not. Optionally you can
use the symbolic versions from Java (&&, ||, and !). This makes typical control flow code easier to understand.
The for loop in Gosu is similar to the Java 1.5 syntax:
for( ad in addressList ) {
print( ad.Id )
}
This works with arrays or any Iterable object. Despite appearances, the variable is strongly typed. Gosu infers
the type based on the iterated variable’s type. In the previous example, if addressList has type Address[], then
ad has type Address. If the addressList variable is null, the for statement is skipped entirely, and Gosu gener-
ates no error. In contrast, Java throws an null pointer exception if the iterable object is null.
If you want an index within the loop, use the following syntax to access the zero-based index:
for( a in addressList index i) {
print( a.Id + " has index " + i)
}
Gosu has native support for intervals, which are sequences of values of the same type between a given pair of
endpoint values. For instance, the set of integers beginning with 0 and ending with 10 is an integer interval. If it
is a closed interval (contains the starting and ending values), it contains the values 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.
The Gosu shorthand syntax for this is 0..10. Intervals are particularly useful to write concise easy-to-understand
for loops:
for( i in 1..10 ) {
print( i )
}
You can optionaly specify an open interval at one or both ends of the interval, meaning not to include the speci-
fied values. The Gosu syntax 1|..|10 means an open interval on both sides, which means the values from 2
through 9.
Intervals do not need to represent numbers. Intervals can be a variety of types including numbers, dates, or other
abstractions such as names. Gosu includes the built-in shorthand syntax (the two periods, shown earlier) for
intervals of dates and common number types. You can also add custom interval types that support iterable
comparable sequences. As long as your interval type implements the required interfaces, you can use your new
intervals in for loop declarations:
for( i in new ColorInterval("red", "blue")) {
print( i )
}
Gosu does not have a direct general purpose equivalent of the Java three-part for declaration:
for ( i =1 ; i <20 ; ++i )
However, in practice the use of intervals makes most typical use of this pattern unnecessary, and you can use a
Gosu while loop to duplicate this pattern.
To use intervals with for loops, they must be an iterative interval. You can choose to make custom non-iterative
intervals if you want. They are mainly useful for math and theoretical work. For example, represent non-count-
able values like the infinite number of real numbers between two other real numbers.
The Gosu switch statement can test any type of object, with a special default case at the end:
var x = "b"
switch( x ) {
case "a":
print("a")
break
case "b":
print("b")
break
default:
print("c")
}
In Gosu, you must put a break statement at the end of each case to jump to the end of the switch statement.
Otherwise, Gosu falls through to the next case in the series. For example, for the previous example if you
remove the break statements, the code prints both "b" and "c". This is the same as Java, although some
languages do not require the break statement to prevent falling through to the next case.
Blocks
Gosu supports in-line functions that you can pass around as objects. Some languages call these closures or
lambda expressions. In Gosu, these are called blocks.
To define a block
1. start with the \ character
3. add the -> characters, which mark the beginning of the block’s body
4. finally, add either a statement list surrounded by curly braces: { and }, or a Gosu expression.
For more information about blocks, see “Gosu Blocks” on page 165.
The following block multiplies a number with itself, which is known as squaring a number:
var square = \ x : Number-> x * x / /no need for braces here (it is an expression, not statements)
var myResult = square(10) // call the block
For more information about blocks, see “Gosu Blocks” on page 165. For more information about collections
enhancement methods, many of which use blocks, see “Collections” on page 183.
For more information, see “Gosu Block Shortcut for Anonymous Inner Classes Implementing an Interface” on
page 143.
Enhancements
Gosu provides a feature called enhancements, which allow you to add functions (methods) and properties to
other types. This is especially powerful for enhancing native Java types, and types defined in other people’s code.
For example, Gosu includes built-in enhancements on collection classes (such as java.util.List) that signifi-
cantly improve the power and readability of collections-related code. For example, the example mentioned
earlier takes a list of String objects, sorts it by length of each String, and iterates across the result list to print
each item:
strings.sortBy( \ str -> str.Length ).each( \ str -> print( str ) )
This works because the sortBy and each methods are Gosu enhancement methods on the List class. Both
methods return the result list, which makes them useful for chaining in series like this.
For more information, see “Enhancements” on page 161.
Collections
Gosu provides several features to make it easy to use collections like lists and maps. Gosu directly uses the built-
in Java collection classes like java.util.ArrayList and java.util.Hashmap. This makes it especially easy to
use Gosu to interact with pre-existing Java classes and libraries.
In addition, Gosu adds the following features:
• Shorthand syntax for creating lists and maps that is easy to read and still uses static typing:
var myList = {"aa", "bb}
var myMap = {"a" -> "b", "c" -> "d"}
• Shorthand syntax for getting and setting elements of lists and maps
var myList = {"aa", "bb}
myList[0] = "cc"
var myMap = {"a" -> "b", "c" -> "d"}
var mappedToC = myMap["c"]
• Gosu includes built-in enhancements that improve Java collection classes. Some enhancements enable you to
use Gosu features that are unavailable in Java. For example, the following Gosu code initializes a list of
String objects and then uses enhancement methods that use Gosu blocks, which are in-line functions. (See
“Blocks” on page 16).
// use Gosu shortcut to create a list of type ArrayList<String>
var myStrings = {"a", "abcd", "ab", "abc"}
// iterate across the list and run arbitrary code for each item:
resortedStrings.each( \ str -> print( str ) )
Notice how the collection APIs are chainable. For readability, you can also put each step on separate lines. The
following example declares some data, then searches for a subset of the items using a block, and then sorts the
results.
var minLength = 4
var strings = { "yellow", "red", "blue" }
For example:
• Gosu can instantiate Java types
• Gosu can manipulate Java objects (and primitives) as native Gosu objects.
• Gosu can get variables from Java types
• Gosu can call methods on Java types. For methods that look like getters and setters, Gosu exposes methods
instead as properties.
• Gosu extends and improves many common Java types using Gosu enhancements. (See “Enhancements” on
page 17.)
• You can also extend Java types and implement Java interfaces.
For more information, see “Java and Gosu” on page 235.
To create a class, use the class keyword, followed by the class name, and then define the variables, then the
methods for the class. To define one or more constructor (object instance initialization) methods, use the
construct keyword. The following is a simple class with one constructor that requires a String argument:
class ABC {
construct( id : String ) {
}
}
Note: You can optionally specify that your class implements interfaces. See “Interfaces” on page 22.
To create a new instance of a class, use the new keyword in the same way as in Java. Pass any constructor argu-
ments in parentheses. Gosu decides what version of the class constructor to use based on the number and types of
the arguments. For example, the following calls the constructor for the ABC class defined earlier in this topic:
var a = new ABC("my initialization string")
Gosu improves on this basic pattern and introduces a standard compact syntax for property initialization during
object creation. For example, suppose you have the following Gosu code:
var myFileContainer = new my.company.FileContainer()
myFileContainer.DestFile = jarFile
myFileContainer.BaseDir = dir
myFileContainer.Update = true
myFileContainer.WhenManifestOnly = ScriptEnvironment.WHEN_EMPTY_SKIP
After the first line, there are four more lines, which contain repeated information (the object variable name).
You can optionally use Gosu object initializers to simplify this code to only a couple lines of code:
var myFileContainer = new my.company.FileContainer() { :DestFile = jarFile, :BaseDir = dir,
:Update = true, :WhenManifestOnly = ScriptEnvironment.WHEN_EMPTY_SKIP }
You can also choose to list each initialization on its own line, which takes up more lines but is more readable:
var myFileContainer = new my.company.FileContainer() {
:DestFile = jarFile,
:BaseDir = dir,
:Update = true,
:WhenManifestOnly = ScriptEnvironment.WHEN_EMPTY_SKIP
}
Unlike Java, you can omit the type name entirely in a new expression if the type is known from its context. For
example:
class Person {
private var _name : String as Name
private var _age : int as Age
}
class Tutoring {
private var _teacher : Person as Teacher
private var _student : Person as Student
}
// declare a variable as a specific type to omit the type name in the "new" expression
// during assignment to that variable
var p : Person
var t : Tutoring
p = new() // notice the type name is omitted
t = new() // notice the type name is omitted
// if a class var or other data property has a declared type, optionally omit type name
t.Teacher = new()
t.Student = new()
// optionally OMIT 'new' keyword and still use the Gosu initialization syntax
t.Student = { :Name = "Bob Smith", :Age = 30 }
For more details, see “Creating and Instantiating Classes” on page 128 and “New Object Expressions” on
page 86.
Functions
Declare a function using the function keyword. When a function is part of another type, a function is called a
method. In Gosu, types follow the variable or function definition, separated by a colon. In contrast, Java types
precede the variable or parameter name with no delimiter. To return a value, add a statement with the return
keyword followed by the value. The following simple function returns a value:
public function createReport( user : User) : Boolean {
return ReportUtils.newReport(user, true)
}
Method invocation in Gosu looks familiar to programmers of imperative languages, particularly Java. Just use
the period symbol followed by the method name and the argument list in parentheses:
obj.createReport( myUser )
Pass multiple parameters (including Gosu expressions) delimited by commas, just as in Java:
obj.calculate(1, t.Height + t.Width + t.Depth)
In some cases, such as in-line functions in Gosu programs, functions are not attached to a class or other type. In
such cases, simply call them. As you saw in earlier examples, there is a rare globally-available function for any
Gosu code, called print. Call that function with a String to write data to the system console or other default
output stream. For example, the following prints text to the console:
print("Hello Gosu!")
Gosu supports access control modifiers (public, private, internal, and protected) and they have the same
meaning as in Java. For example, if you mark a method public, any other code can call that method. For more
information, see “Access Modifiers” on page 136.
Gosu also supports static methods, which means methods on the type rather than on object instances. See “Static
Members” on page 21.
If the return type is not void, all possible code paths must return a value in a method that declares a return type.
In other words, if any code path contains a return statement, Gosu requires a return statement for all possible
paths through the function. The set of all paths includes all outcomes of conditional execution, such as if and
switch statements. This is identical to the analogous requirement in Java. The Gosu editor automatically notifies
you at compile time of this issue if it happens. For details, see “Gosu Functions” on page 106.
One special difference between Gosu and some languages (including Java) is full support in Gosu for proper-
ties, which are dynamic getter and setter methods for values. To set or get properties from an object (internally,
Gosu calls the property getter and setter methods), use natural syntax. Type the period (.) character followed by
the property name just as you would for an object variable:
var s = myobj.Name
myobj.Name = "John"
In addition, Gosu has a special null-safety behavior with pure property paths, which are the form
obj.Property1.Property2.Property3. For more information, see “Property Accessor Paths are Null Safe” on
page 21.
Define a property accessor function (a property getter) using the declaration property get instead of function.
Define a setter function using function declaration property set instead of function. These property accessors
can dynamically get or set the property, depending on whether it is defined as property get or property set.
Properties can be read/write, or can be read-only or write-only. Gosu provides a special shortcut to expose
internal variables as public properties with other names. Use the syntax as PROPERTY_NAME as follows in a class
definition for a variable. This makes it easy to separate the internal implementation of variables from how you
expose properties to other code
var _name : String as Name //Exposes the _name field as a readable and writable 'Name' property
Think of this is a shortcut for creating a property get function and a property set function for each variable.
This is the standard and recommended Gosu style for designing public properties. (In contrast, for new Gosu
code do not expose actual class variables as public, although Gosu supports it for compatibility with Java.)
The following is a simple Gosu class definition:
package example // declares the package (namespace) of this class
class Person {
var _name : String as Name // Exposes the _name field as a readable and writable 'Name' property
var _id : String // vars are private by default
//Constructors are like functions called construct but omit the function keyword.
// You can supply multiple method signatures with different numbers or types of arguments
construct( id : String ){
_id = id
}
property get ID() : String { //_id is exposed as a read only 'ID' property
return _id
}
Gosu exposes these methods as the Radius property, which is readable and writable. That means you could use
straightforward code such as:
circle.Radius = 5 // property SET
print(circle.Radius) // property GET
For a detailed example, see “Java Get and Set Methods Convert to Gosu Properties” on page 237.
Gosu provides a way to access properties in a way that is tolerant of unexpected null values, a feature called null
safety. To do this, add a question mark before the period to transform the operator into the null-safe version. For
example:
obj?.Property1?.Property2?.Property3
In most cases, if any object to the left of the ?. operator is null, the expression returns null and Gosu does not
throw a null pointer exception (NPE). Using null-safe property paths tends to simplify real-world code. Gosu
null-tolerant property accessor paths are a good reason to expose data as properties in Gosu classes and inter-
faces rather than as setter and getter methods.
There are additional null-safe operators. For example, specify default values with code like:
// Set display text to the String in the txt variable, or if it is null use "(empty)"
var displayText = txt ?: "(empty)"
For more about Gosu null safety, see “Null Safety for Properties Other Operators” on page 30.
Static Members
Gosu supports static members on a type. This includes variables, functions, property declarations, and static
inner classes on a type. The static quality means that the member exists only on the type (which exists only once),
not on instances of the type. The syntax is simple. After a type reference (just the type name), use the period (.)
character followed by the property name or method call. For example:
MyClass.PropertyName // get a static property name
MyClass.methodName() // call a static method
In Gosu, for each usage of a static member you must qualify the class that declares the static member. However,
you do not need to fully-qualify the type. In other words, you do not need to include the full package name if the
type is already imported with a uses statement or is already in scope. For example, to use the Math class’s cosine
function and its static reference to value PI, use the syntax:
Math.cos(Math.PI * 0.5)
Gosu does not have an equivalent of the static import feature of Java 1.5, which allows you to omit the enclosing
type name before static members. In the previous example, this means omitting the text Math and the following
period symbol. This is only a syntax difference for using static members in Gosu code, independent of whether
the type you want to import is a native Gosu or Java type.
To declare a type as static for a new Gosu class, use the static keyword just as in Java. For details, see “Modi-
fiers” on page 135.
Interfaces
Gosu supports interfaces, including full support for Java interfaces. An interface is a set of method signatures
that a type must implement. It is like a contract that specifies the minimum set of functionality to be considered
compatible. To implement an interface, use the interface keyword, then the interface name, and then a set of
method signatures without function bodies. The following is a simple interface definition using the interface
keyword:
package example
interface ILoadable {
function load()
}
Next, a class can implement the interface with the implements keyword followed by a comma-delimited list of
interfaces. Implementing an interface means to create a class that contains all methods in the interface:
package example
function load() {
print("Loading...")
}
}
If you use the expansion operator on a list, it gets a property from every item in the list and returns all instances
of that property in a new list. It works similarly with arrays.
Let us consider the previous example names*.Length. Assume that names contains a list of String objects, and
each one represents a name. All String objects contain a Length field. The result of the above expression would
be a list containing the same number of items as in the original list. However, each item is the length (the
String.Length property) of the corresponding name.
Gosu infers the type of the list as appropriate parameterized type using Gosu generics, an advanced type feature.
For more information about generics, see “Generics in Gosu” on page 32. Similarly, Gosu infers the type of the
result array if you originally call the operator on an array.
This feature also works with both arrays and lists. For detailed code examples, see “List and Array Expansion
(*.)” on page 187.
Comparisons
In general, the comparison operators work you might expect if you were familiar with most programming
languages. There are some notable differences:
• The operators >, <, >=, and <= operators work with all objects that implement the Comparable interface, not
just numbers.
• The standard equal comparison == operator implicitly uses the equals method on the first (leftmost) object.
This operator does not check for pointer equality. It is null safe in the sense that if either side of the operator
is null, Gosu does not throw a null pointer exception. (For related information, see “Property Accessor Paths
are Null Safe” on page 21.)
Note: In contrast, in the Java language, the == operator evaluates to true if and only if both operands have
the same exact reference value. In other words, it evaluates to true if they refer to the same object in
memory. This works well for primitive types like integers. For reference types, this usually is not what you
want to compare. Instead, to compare value equality, Java code typically uses object.equals(), not the ==
operator.
• There are cases in which you want to use identity reference, not simply comparing the values using the under-
lying object.equals() comparison. In other words, some times you want to know if two objects literally
reference the same in-memory object. Gosu provides a special equality operator called === (three equals
signs) to compare object equality. It always compares whether both references point to the same in-memory
object. The following examples illustrate some differences between == and === operators:
Case Sensitivity
Gosu language itself is case insensitive, but Gosu compiles and runs faster if you write all Gosu as case-sensitive
code matching the declaration of the language element. Additionally, proper capitalization makes your Gosu
code easier to read. For more information, including Gosu standards for capitalizing your own language
elements, see “Gosu Case Sensitivity” on page 33.
• Gosu supports additional compound assignment statements that mirror other common operators. See “Vari-
able Assignment” on page 98 for the full list.
For example, to increment the variable i by 1:
i
It is important to note that these operators always form statements, not expressions. This means that the
following Gosu is valid:
var i = 1
while(i < 10) {
i++
print( i )
}
However, the following Gosu is invalid because statements are impermissible in an expression, which Gosu
requires in a while statement:
var i = 1
while(i++ < 10) { // Compilation error!
print( i )
}
Gosu supports the increment and decrement operator only after a variable, not before a variable. In other words,
i++ is valid but ++i is invalid. The ++i form exists in other languages to support expressions in which the result
is an expression that you pass to another statement or expression. As mentioned earlier, in Gosu these operators
do not form an expression. Thus you cannot use increment or decrement in while declarations, if declarations,
and for declarations.
See “Variable Assignment” on page 98 for more details.
construct() {
_clipboardPart = new ClipboardPart( this )
}
}
In this example, the class definition uses the delegate keyword to delegate implementation of the
IClipboardPart interface. The constructor creates a concrete instance of an object (of type ClipboardPart) for
that class instance variable. That object must have all the methods defined in the IClipboardPart interface.
You can use a delegate to represent (handle methods for) multiple interfaces for the enclosing class. Instead of
providing a single interface name, specify a comma-separated list of interfaces. For example:
private delegate _employee represents ISalariedEmployee, IOfficer
The Gosu type system handles the type of the variable in the previous example using a special kind of type called
a compound type.
For more information, see “Composition” on page 151.
Concurrency
If more than one Gosu thread interacts with data structures that another thread needs, you must ensure that you
protect data access to avoid data corruption. Because this topic involves concurrent access from multiple threads,
this issue is generally called concurrency. If you design your code to safely get or set concurrently-accessed data,
your code is called thread safe.
// a property get function uses the lock and calls another method for the main work
property get SomeProp() : Object
using( _lock ) {
return _someVar.someMethod() // do your work here and Gosu synchronizes it, and handles cleanup
}
• Scoping classes (pre-scoped maps). Scope-related utilities in the class gw.api.web.Scopes help synchronize
and protect access to shared data. These APIs return Map objects into which you can safely get and put data
using different scope semantics.
• Lazy concurrent variables. The LazyVar class (in gw.util.concurrent) implements what some people call a
lazy variable. This means Gosu constructs it only the first time some code uses it. For example the following
code is part of a class definition that defines the object instance. Only at run time at the first usage of it does
Gosu run the Gosu block that (in this case) creates an ArrayList:
var _lazy = LazyVar.make( \-> new ArrayList<String>() )
• Concurrent cache. The Cache class (in gw.util.concurrent) declares a cache of values you can look up
quickly and in a thread-safe way. It declares a concurrent cache similar to a Least Recently Used (LRU)
cache. After you set up a cache object, to use it just call its get method and pass the input value (the key). If
the value is in the cache, it simply returns it from the cache. If it is not cached, Gosu calls the block and calcu-
lates it from the input value (the key) and then caches the result. For example:
print(myCache.get("Hello world")
For more information about concurrency APIs, see “Concurrency” on page 269
Exceptions
Gosu supports the full feature set for Java exception handling, including try/catch/finally blocks. However,
unlike Java, no exceptions are checked. Standard Gosu style is to avoid checked exceptions where possible. You
can throw any exception you like in Gosu, but if it is not a RuntimeException, Gosu wraps the exception in a
RuntimeException.
Catching Exceptions
The following is a simple try/catch/finally:
try {
user.enter(bar)
} catch( e ){
print("failed to enter the bar!")
} finally {
// cleanup code here...
}
Note that the type of e is not explicit. Gosu infers the type of the variable e to be Throwable.
If you need to handle a specific exception, Gosu provides a simplified syntax to make your code readable. It lets
you catch only specific checked exceptions in an approach similar to Java’s try/catch syntax. Simply declare
the exception of the type of exception you wish to catch:
catch( e : ThrowableSubclass )
For example:
try {
doSomethingThatMayThrowIOException()
}
catch( e : IOException ) {
// Handle the IOException
}
Throwing Exceptions
In Gosu, throw an exception with the throw statement, which is the throw keyword followed by an object.
The following example creates an explicit RuntimeException exception:
if( user.Age < 21 ) {
throw new RuntimeException("User is not allowed in the bar")
}
You can also pass a non-exception object to the throw statement. If you pass a non-exception object, Gosu first
coerces it to a String. Next, Gosu wraps the String in a new RuntimeException. As a consequence, you could
rewrite the previous throw code example as the concise code:
if( user.Age < 21 ) {
throw "User is not allowed in the bar"
}
Annotations
Gosu annotations are a simple syntax to provide metadata about a Gosu class, constructor, method, class vari-
able, or property. This annotation can control the behavior of the class, the documentation for the class.
This code demonstrates adding a @Throws annotation to a method to indicate what exceptions it throws.
class MyClass{
You can define custom annotations, and optionally have your annotations take arguments. If there are no argu-
ments, you can omit the parentheses.
You can get annotations from types at run time.
Gosu supports named arguments syntax for annotations:
@MyAnnotation(a = "myname", b = true)
Gosu Templates
Gosu supports in-line dynamic templates using a simple syntax. Use these to combine static text with values
from variables or other calculations Gosu evaluates at run time. For example, suppose you want to display text
with some calculation in the middle of the text:
var s = "One plus one equals ${ 1 + 1 }."
Template expressions can include variables and dynamic calculations. Gosu substitutes the run time values of the
expressions in the template. The following is an example of a method call inside a template:
var s2 = "The total is ${ myVariable.calculateMyTotal() }."
At compile time, Gosu ensures all template expression are valid and type safe. At run time, Gosu runs the
template expression, which must return a String value or a type that can cast to a String.
In addition to in-line Gosu templates, Gosu supports a powerful file-based approach for Gosu templates with
optional parameter passing. Any use of the parameters is validated for type-safety, just like any other Gosu code.
For example, use a template to generate a customized notification email, and design the template to take parame-
ters. Parameters could include type safe references to the recipient email address, the sender email address, and
other objects. Insert the parameters directly into template output, or call methods or get properties from parame-
ters to generate your customized email report.
For more information, see “Gosu Templates” on page 243.
The following Gosu code manipulates XML objects using XSD-based types:
uses xsd.driver.DriverInfo
uses xsd.driver.DriversLicense
uses java.util.ArrayList
For example, the following Gosu code uses an XSD called demochildprops to add two child elements and then
print the results:
// create a new element, whose type is *automatically* in the namespace of the XSD
var e = new com.guidewire.pl.docexamples.gosu.xml.demochildprops.Element1()
// create a new CHILD element that is legal in the XSD, and add it as child
var c1 = new com.guidewire.pl.docexamples.gosu.xml.demochildprops.anonymous.elements.Element1_Child1()
e.addChild(c1)
// create a new CHILD element that is legal in the XSD (and which requires an int), and add it as child
var c2 = new com.guidewire.pl.docexamples.gosu.xml.demochildprops.anonymous.elements.Element1_Child2()
c2.$Value = 5 // this line automatically creates an XMLSimpleType -- but code is easy to read
e.addChild(c2)
2. In your Gosu program, tell Gosu where to find your other Gosu classes and Java classes by adding the class-
path statement.
Typically you would place Java classes, Gosu classes, or libraries in subdirectories of your main Gosu program.
Copy your class file for the class mypackage.MyClass to the location:
C:\gosu\myprograms\test1\src\mypackage\MyClass.class
For this example, add two directories to the class path with the following Gosu statement:
classpath "src,lib"
For more details, see “The Structure of a Gosu Program” on page 59.
For instance, if any code tried to call this method and pass an integer instead of a Person, the code fails with a
type mismatch compiler error. That is because the parameter value is not a Person, which is the contract between
the function definition and the code that calls the function.
Similarly, Gosu ensures that all property access on the Person object (LastName and FirstName properties) are
valid properties on the class definition of Person. If the code inside the function called any methods on the
object, Gosu also ensures that the method name you are calling actually exists on that type.
Within the Gosu editor, any violations of these rules become compilation errors. This means that you can find a
large class of problems at compile time rather than experience unpleasant surprises at run time.
Type Inference
As mentioned earlier, Gosu supports type inference, in which Gosu sometimes can infer (determine) the type
without requiring explicit type declarations in the Gosu code. For instance, Gosu can determine the type of a
variable from its initialized value.
var length = 12
var list = new java.util.ArrayList()
In the first line, Gosu infers the length variable has the type int. In the second line, Gosu infers the type of the
list variable is of type ArrayList. In most cases, it is unnecessary to declare a variable’s type if Gosu can deter-
mine the type of the initialization value.
Gosu supports explicit declarations of the type of the variable during declaration using the syntax:
var c : MyClassName = new MyClassName()
However, for typical code, the Gosu coding style is to omit the type and use type inference to declare the vari-
able’s type.
Another standard Gosu coding style is to use a coercion on the right side of the expression with an explicit type.
For example, suppose you used a class called Vehicle and it had a subclass Car. If the variable v has the compile
time type Vehicle, the following code coerces the variable to the subtype:
var myCar = v as Car
By default, the period operator is not null-safe. This means that if the value on the left side of the period evalu-
ates to null at runtime, Gosu throws a null pointer exception (NPE). For example, obj.PropertyA.PropertyB
throws an exception if obj or obj.PropertyA are null at run time.
Gosu provides a variant of the period operator that is always null-safe for both property access and method
access. The null-safe period operator has a question mark before it: ?.
If the value on the left of the ?. operator is null, the expression evaluates to null.
For example, the following expression evaluates left-to-right and contains three null-safe property operators:
obj?.PropertyA?.PropertyB?.PropertyC
If any object to the left of the period character is null, the null-safe period operator does not throw a null pointer
exception (NPE) and the expression returns null. Gosu null-safe property paths tends to simplify real-world
code. Often, a null expression result has the same meaning whether the final property access is null or whether
earlier parts of the path are null. For such cases in Gosu, do not bother to check for null value at every level of
the path. This makes your Gosu code easier to read and understand.
For example, suppose you had a variable called house, which contained a property called Walls, and that object
had a property called Windows. You could get the Windows value with the following syntax:
house.Walls.Windows
In some languages, you must worry that if house is null or house.Walls is null, your code throws a null
pointer exception. This causes programmers to use the following common coding pattern:
// initialize to null
var x : ArrayList<Windows> = null
// check earlier parts of the path for null to avoid a null pointer exceptions (NPEs)
if( house != null and house.Walls != null ) {
x = house.Walls.Windows
}
The following concise Gosu code is equivalent to the previous example and avoids any null pointer exceptions:
var x = house?.Walls?.Windows
If house is null, Gosu throws an NPE exception. Gosu assumes that method calls might have side effects, so
Gosu cannot quietly skip the method call and return null.
In contrast, a null-safe method call does not throw an exception if the left side of the period character is null.
Gosu just returns null from that expression. In contrast, using the ?. operator calls the method with null safety:
house?.myaction()
If house is null, Gosu does not throw an exception. Gosu simply returns null from the expression.
See Also
• For more examples and discussion, see “Handling Null Values In Expressions” on page 95
IMPORTANT For more information about property accessor paths and designing your APIs around
this feature, see “Handling Null Values In Expressions” on page 95.
Generics in Gosu
Generics are a way of abstracting behavior of a type to support working with multiple types of objects. Generics
are particularly useful for implementing collections (lists, maps) in a type-safe way. At compile time, each use of
the collection can specify the specific type of its items. For example, instead of just referring to a list of objects,
you can refer to a list of Address objects or a list of Vehicle objects. To specify a type, add one or more parame-
ters types inside angle brackets (< and >). For example:
uses java.util.*
This is called parameterizing a generic type. Read ArrayList<Date> in English as “an array list of date objects”.
Read Map<String, Date> as “a map that maps String to Date”.
The Gosu generics implementation is compatible with the Java 1.5 generics implementation, and adds additional
improvements:
• Gosu type inference greatly improves readability. You can omit unnecessary type declarations, which is espe-
cially important for generics because the syntax tends to be verbose.
• Gosu generics support array-style variance of different generic types. In Java, this is a compilation error, even
though it is natural to assume it works.
In Java, this is a compilation error:
ArrayList<Object> mylist;
mylist = new ArrayList<String>()
The analogous Gosu code works:
var mylist : ArrayList<Object>
mylist = new ArrayList<String>()
• Gosu types preserve generic type information at run time. This Gosu feature is called reified generics. This
means that in complex cases you could check the exact type of an object at run time, including any parameter-
ization. In contrast, Java discards this information completely after compilation, so it is unavailable at run
time.
Note: Even in Gosu, parameterization information is unavailable for all native Java types because Java does
not preserve this information beyond compile time. For example the run time type of
java.util.List<Address> in Gosu returns the unparameterized type java.util.List.
• Gosu includes shortcut initialization syntax for common collection types so you do not need to actually see
the generics syntax, which tends to be verbose. For example, consider the following Gosu:
var strlist = {"a", "list", "of", "Strings"}
Despite appearances, the strlist variable is statically typed. Gosu detects the types of objects you are initial-
izing with and determines using type inference that strlist has the type
java.util.ArrayList<java.util.String>. This is generics syntax for the meaning “a list of String
objects”.
For more information, see “Gosu Generics” on page 173.
IMPORTANT Later versions of the Gosu community release will include more APIs and docu-
mentation about creating your own custom Gosu type loaders.
The following table lists various language elements and the standard Gosu capitalization for those language
elements:
It is best to change any existing code to be case sensitive, and write any new code to follow these guidelines.
IMPORTANT It is best to write all Gosu code as case-sensitive for all type names, variable names,
keywords, method names, property names, package names, and other language elements. If you do not,
your code compiles slower, runs slower, and requires more memory at compile time and at run time.
However, Gosu expressions and code executes case-insensitively in this release. That means that effectively
there is no difference in behavior in the following two statements in Gosu even though the method currentDate
has two different case variants:
// Valid expressions
var date1 = gw.api.util.DateUtil.currentDate()
var date2 = gw.api.util.DateUtil.currentdate()
If you define an item using a case variation of a previously defined item, the Gosu editor displays an error
message that the item was previously defined.
var date1 = gw.api.util.DateUtil.currentDate()
var date2 = gw.api.util.DateUtil.currentdate()
At run time, Gosu treats variables date1 and Date1 the same in Gosu code. Therefore the second variable defini-
tion (Date1) is invalid.
Use the Gosu editor Code Completion feature to enter the names of types and properties correctly. This ensures
standard capitalization.
Remember to use initial lower-case for your own variables (local variables and class variables). Use an initial
uppercase letter for type names and property names, and initial lowercase letters for method names.
// NO - generally do not rely on whitespace for line breaks. It is hard to read and errors are common.
print(x) print(y)
// NO - generally do not rely on whitespace for line breaks. It is hard to read and errors are common.
var pnum = Policy.PolicyNumber cnum = Claim.ClaimNumber
IMPORTANT Generally speaking, omit semicolon characters in Gosu. Semicolons are unnecessary in
almost all cases. However, standard Gosu style to use semicolons between multiple Gosu statements on
one line (such as in short Gosu block definitions).
Invalid Statements
var pnum = Policy.PolicyNumbercnum = Claim.ClaimNumber
Gosu Comments
Comment your Gosu code as you write it. The following table lists the comment styles that Gosu supports.
• application • new
• as • null
• break • override
• case • package
• catch • private
• class • property
• continue • protected
• default • public
• do • readonly
• else • request
• eval • return
• except • session
• execution • set
• extends • static
• finally • super
• final • switch
• find • this
• for • try
• foreach • typeas
• function • typeis
• get • typeof
• hide • unless
• implements • uses
• index • var
• interface • void
• internal • while
• native
Required
Difference Java Gosu change?
General Differences
Gosu language itself is case insen- a.B = c.D a.B = c.D Optional
sitive, but Gosu compiles and runs B and D must exactly match the Match the code capitalization to
faster if you write Gosu as case-
field declarations. match the property declarations.
sensitive code. Match the declara-
tion of each language element. See Other capitalizations work, but are
“Case Sensitivity” on page 23. not recommended, such as:
a.b = c.d
Omit semicolons in most code. x = 1; x = 1 Optional
Gosu supports the semicolon, but
standard coding style is to omit it.
(one exception is in block declara-
tions with multiple statements)
Print to console with the print System.out.println("hello"); print("hello") Optional
function. For compatibility with Java
code while porting to Gosu, you can uses java.lang.System
optionally call the Java class System.out.println("hello
java.lang.System. world")
Required
Difference Java Gosu change?
In variable declarations, use the var Auto c = new Auto() Type inference Required
keyword. Typically you can rely on var c = new Auto()
Gosu type inference and omit
Explicit:
explicit type declaration. To explicitly
declare the type, list the type after var c : Auto = new Auto()
the variable, delimited by a colon. Type inference with coercion:
You can also coerce the expression var c = new Auto() as Vehicle
on the right side, which affects type
inference
To declare variable argument func- public String // function declaration Required
tions, also called vararg functions, format(Object... args); public function format(args :
Gosu does not support the special Object[])
Java syntax. In other words, Gosu
does not support arguments with // method call using
“...” declarations, which indicates // initializer syntax
variable number of arguments. var c = format({"aa","bb"})
Instead, design APIs to use arrays
or lists.
To call variable argument functions,
pass an array of the declared type.
Internally, in Java, these variable
arguments are arrays. Gosu array
initialization syntax is useful for call-
ing these types of methods.
Gosu supports the unary operator if (++i > 2) { i++ Required
assignment statements ++ and --. // if (i > 2) {
However: } //
• only use the operator after the }
variable (such as i++)
• these only form statements not
expressions.
There are other supported com-
pound assignment statements, such
as +=, -=, and others. see “Variable
Assignment” on page 98.
For static members (static methods cos(PI * 0.5) Math.cos(Math.PI * 0.5) Required
and static properties), in Gosu you Note that you do not need to fully if you omit
must qualify the type on which the qualify the type as type
static member appears. Use the java.lang.Math. names in
period character to access the your Java
member. The type does not need to code
be fully qualified, though. before
static
members
Type System
For coercions, use the as keyword. int x = (int) 2.1 // Gosu style Optional
var x = 2.1 as int
Optionally, Gosu supports Java-
style coercion syntax for compatabil-
ity. //Java compatability style
var x = (int) 2.1
Check if an object is a specific type myobj instanceof String myobj typeis String Required
or its subtypes using typeis. This is
similar to the Java instanceof
operator.
Required
Difference Java Gosu change?
Gosu generics support array-style In Java, this is a compilation error: The analogous Gosu code works: Optional
variance of different generic types. ArrayList<Object> mylist; var mylist : ArrayList<Object>
In Java, this is a compilation error, mylist = new mylist = new
even though it is natural to assume ArrayList<String>() ArrayList<String>()
it works
In Gosu, type names are first-class Class sc = String.class var sc = String Required
symbols for the type. Do not get the
class property from a type name.
Defining Classes
Declare that you use specific types import com.abc.MyClass uses com.abc.MyClass Required
or package hierarchies with the key-
word uses rather than import.
To declare one or more class con- class ABC { class ABC { Required
structors, write them like functions public ABC ( String id ){ construct( id : String ) {
called construct but omit the key- } }
word function. Gosu does not sup- } }
port Java-style constructors.
Control Flow
Required
Difference Java Gosu change?
The for loop syntax in Gosu is dif- int[] numbers = {1,2,3}; var numbers : int[] = {1,2,3}; Required
ferent for iterating across a list or for (int item : numbers) { for (item in numbers) {
array. Use the same Gosu syntax for // //
iterating with any iterable object (if it } }
implements Iterable). Optionally
add “index indexVar” before the
close parenthesis to create an addi-
tional index variable. This index is
zero-based. If the object to iterate
across is null, the loop is skipped
and there is no exception (as there
is in Java).
The for loop syntax in Gosu is dif- for(int i=1; i<20; i++){ for (item in 20) { Required
ferent for iterating a loop an integer // //
number of times. The loop variable } }
contains the a zero-based index.
Using Gosu intervals:
Gosu has native support for inter- for( i in 1..50 ) {
vals, which are sequences of values
print( i )
of the same type between a given
pair of endpoint values. For }
instance, the set of integers begin- verbose style:
ning with 0 and ending with 10 is the var i = 0
shorthand syntax 0..10. Intervals while (i < 20) {
are particularly useful to write con-
//
cise easy-to-understand for loops.
i++
Gosu does not support the for(initial- }
ize;compare;increment) syntax in
Java. However, you can duplicate it
using a while statement (see exam-
ple).
Gosu blocks, which are in-line func- n/a \ x : Number -> x * x Optional
tions that act like objects. They are
especially useful with the Gosu col-
lections enhancements See “Gosu
Blocks” on page 165. Blocks can
also be useful as a shortcut for
implementing one-method inter-
faces (see “Blocks as Shortcuts for
Anonymous Classes” on page 171).
Native XML support and XSD sup- n/a var e = schema.parse(xmlText) Optional
port. See “Gosu and XML” on
page 195.
Required
Difference Java Gosu change?
Native support for consuming web n/a extAPI.myMethod(1, true, "c") Optional
services with syntax similar to native
method calls. See “Consuming WS-I
Web Service Overview” on
page 225.
Native String templates and file- n/a var s = "Total = ${ x }." Optional
based templates with type-safe
parameters. See “Gosu Templates”
on page 243.
Gosu uses the Java-based collec- // easy initialization Optional
tions APIs but improves upon them: var strs = {"a", "ab", "abc"}
• Simplified initialization syntax that
still preserves type safety. // array-like "set" and "get"
• Simple array-like syntax for get- strs[0] = "b"
ting and setting values in lists, var val = strs[1]
maps, and sets
• Gosu adds new methods and
// new APIs on Java
properties to improve functionality
// collections types
of the Java classes. Some
strList.each(\ str -> {
enhancements use Gosu blocks print(str) } )
for concise flexible code.
For new code, use the Gosu style
initialization and APIs. However, you
can call the more verbose Java style
for compatibility. See “Collections”
on page 183.
List and array expansion operator. n/a names*.Length Optional
See “List and Array Expansion (*.)”
on page 187.
To ask questions about Gosu or offer general feedback on the Gosu language, join and post to the gosu-lang
forum:
http://groups.google.com/group/gosu-lang
To file bug reports, please submit them to the gosu-lang bug tracking system:
http://code.google.com/p/gosu-lang/issues/list
To continue your introduction to the Gosu language, see the following topic: “Getting Started with Gosu
Community Release” on page 43.
System Requirements
The following table lists the system requirements for the community release of Gosu.
The Gosu plugin appears in the list of plugins within the IntelliJ IDEA application itself. You can install the Gosu
plugin from within that user interface.
For installation instructions and full feature list for the Gosu plugin for the IntelliJ IDEA IDE, visit:
http://gosu-lang.org
To run Gosu programs outside the IntelliJ IDE, for example from the command line, download the official Gosu
install available at the same URL. That download includes the latest Gosu language documentation.
Refer to the IntelliJ documentation for complete information about:
• creating new class files
• organizing modules
• refactoring tools
• file management (including Java JAR files)
2. Unzip the file to the desired location on your local disk. The documentation refers to this root directory for
gosu simply as the name Gosu. The Gosu/bin directory contains the binary executables and the Gosu/lib
directory contains the Gosu libraries.
1. Open a DOS command line window (cmd.exe)
5. When you are done, type the one-word command quit, and then press the Enter key.
6. Optionally, you may want to add the Gosu/bin directory to your system path. That allows you to type gosu at
command line, independent of the current working directory. Go to the Start menu and choose Control Panel
System Environment Variables. Next, choose the Path variable. At end of the current path, append a semicolon
and the full path to the bin directory. For example, suppose you installed (copied) the Gosu shell directory to
the path:
C:\gosu\
Add the following to the system path:
;C:\gosu\bin
To test this, close any existing command prompt windows, then open a new command prompt window and
type the word gosu then the type the Enter key.
5. When you are done, type the one-word command quit, and then press the Enter key.
6. For more information about command line options, see “Gosu Programs and Command Line Tools” on
page 57.
Advanced Examples
Servlet Example
The Gosu community release includes an example called Servlet. It is a simple implementation of a web server
servlet implemented in Gosu.
2. Set the system environment variable CATALINA_HOME to the root directory of your Tomcat installation. In
Windows, go to Control Panel System Advanced Set Environment Variables. In the bottom pane, click New and
then create a new variable called CATALINA_HOME with value C:\Program Files\apache-tomcat, or wher-
ever your installation is.
3. Create a servlet folder called GosuServlet in your web server’s webapps directory. For this example, we
assume you are using Apache Tomcat and the directory is called apache-tomcat. Copy the GosuServlet files
- apache-tomcat
- webapps
- GosuServlet
5. Create a web.xml file inside that folder to enable Gosu template support, such as
- GosuServlet
- WEB-INF
- web.xml
In this file paste the following:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>GosuServlet</servlet-name>
<servlet-class>gw.util.servlet.GosuServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GosuServlet</servlet-name>
<url-pattern>*.gst</url-pattern>
</servlet-mapping>
</web-app>
6. Copy HelloWorld.gst from the example example/GosuServlet/src/sample directory into your servlet root
directory. After this step, your file hierarchy looks like:
- apache-tomcat
- webapps
- GosuServlet
- sample
- hello
- HelloWorld.gst
7. Copy all JAR files from the root of the servlet example directory into your servlet WEB-INF directory. Next,
copy the JAR files from the lib subdirectory of the servlet example into your servlet WEB-INF directory. Your
servlet looks like this:
- apache-tomcat
- webapps
- GosuServlet
- WEB-INF
- lib
- gw-gosu-core.jar
- gw-gosu-core-api.jar
- servlet-api
...[the rest of the JAR files]
8. Start up Apache Tomcat. You can do this by running the following script:
apache-tomcat/bin/startup.bat
9. Wait for Tomcat to startup. If you see any servlet startup errors in the console, make a note of them for debug-
ging or bug reporting.
10. Test this in your browser, remembering to set the domain name and port appropriately, such as:
http://localhost:8080/GosuServlet/sample/hello/HelloWorld.gst
The example contains a couple Gosu files and a directory of libraries (including the Hibernate libraries).
The main file is the file src/demo/TestDrive.gsp. This is the main entry point to the example. The file exten-
sion is .gsp, which means this is a Gosu program. A Gosu program is a way to write small scripts or to launch
larger Gosu applications that use Gosu classes or other Java types.
The TestDrive.gsp file has a utility function called configureHibernate, which sets up a map of configuration
properties for Hibernate. It uses the initialization Gosu syntax as follows:
var props = {
"hibernate.dialect" -> "org.hibernate.dialect.HSQLDialect",
"hibernate.connection.driver_class" -> "org.hsqldb.jdbcDriver",
"hibernate.connection.url" -> "jdbc:hsqldb:mem:demodb",
"hibernate.connection.username" -> "sa",
"hibernate.connection.password" -> "",
"hibernate.connection.pool_size" -> "1",
"hibernate.connection.autocommit" -> "true",
"hibernate.cache.provider_class" -> "org.hibernate.cache.NoCacheProvider",
"hibernate.hbm2ddl.auto" -> "create-drop",
//"hibernate.show_sql" -> "true",
"hibernate.transaction.factory_class" -> "org.hibernate.transaction.JDBCTransactionFactory",
"hibernate.current_session_context_class" -> "thread"
}
The resulting type is a java.util.Map<String, String> object, which is not explicit. Gosu infers the type
because of the use of the -> syntax that maps the property (a String) to a value (a String).
The configuration function then sends these properties to the Hibernate system:
var config = new AnnotationConfiguration()
props.eachKeyAndValue( \k, v -> config.setProperty(k, v) )
config.addAnnotatedClass( Book.Type.BackingClass )
return config.buildSessionFactory()
Next, the example begins a database transaction using the Hibernate libraries:
// Add some books
var sn = sessionFactory.CurrentSession
var tx = sn.beginTransaction()
Next, the example creates some new objects to save in the database, and commits them to the database.
sn.save( new Book() {:Author="I.N. Herstein", :Title="Abstract Algebra"} )
sn.save( new Book() {:Author="David Hackett Fischer", :Title="Washington's Crossing"} )
tx.commit()
Finally, the example runs a database query to confirm that the sample worked successfully:
// Find some books
sn = sessionFactory.CurrentSession
tx = sn.beginTransaction()
var query = sn.createQuery( "from " + Book.Type.RelativeName )
for( book in query.iterate() as Iterator<Book> ) {
print( book.Title + " by " + book.Author )
}
tx.commit()
The Gosu code iterates across the results in a for loop. Note the code that casts the query to an iterator:
as Iterator<Book>
By doing this, the code inside the loop can treat the book variable as the correct specific type. That means that it
can access type-specific fields like book.Title and book.Author in a type-safe way.
As you can see, inside the loop is an example of the one global function in Gosu, which is the print function. It
prints a String to the console or standard output.
Another project file is src/demo/Book.gs. It is a Gosu class that defines the structure of the book objects in the
example. Refer to it for details if you plan to implement a Hibernate project in Gosu.
The DynamicType project is a demonstration type loader that demonstrates the unusual power of the Gosu exten-
sible type system without having to type a lot of code.
The purpose of DynamicType is to create a type with the fully-qualified name dynamic.Dynamic that has a few
special behaviors in the Gosu type system:
• Any object can be assigned to a variable of this special type. For example, if a variable has type
dynamic.Dynamic, then you could assign a String, a Map, an ArrayList or any other object to the variable.
Effectively, this is way of creating a non-statically-typed type in Gosu, as opposed to its normal static typing
behavior.
• Method invocations and property invocations can happen dynamically and reflectively. In other words, you
can call a method on an object or get a property from an object, and at compile time Gosu will permit it.
This dynamic type approach is effectively the opposite of the normal way of coding in a statically-typed
language such as Gosu. This is not a normal way of writing Gosu code. This example simply demonstrates that
custom type loader behavior can generate complex new and potentially useful behaviors.
The main files of this project are in the directory src/custom/dyntype. The Gosu type loaders are written in
Java, which is a requirement for Gosu type loaders.
That directory includes the Java files for the type loader for the Dynamic type. These Java files tell Gosu how to,
for example, load a type, how to get properties from a type, and how to expose and invoke methods on the type.
The files have names such as DynamicMethodInfo.java and DynamicTypeLoader.java.
The UseDynamicType example shows how you might use this type in a simple way:
classpath ".."
//typeloader custom.dyntype.DynamicTypeLoader
uses dynamic.Dynamic
foo( "hello" )
In this example, a function has an argument of the special type called Dynamic. The call to the function passes a
String object. This compiles successfully because the dynamic type allows any object to be assigned to it. As a
function parameter, within the function the parameter name value contains the object. The code then calls the
charAt method of the object. Normally, Gosu requires that the declared type contain explicit methods on the
object if you want to call them. In this case, the example type loader allows any method name on the Dynamic
object without compile errors. At run time, the type loader handles the method invocation and if the target object
at run time contains that method, it will succeed.
In this example, the charAt method is a method on a String object, so the code succeeds. If you changed the
code to call some arbitrary method name that String does not possess, such as notRealMethodName, this code
would throw an exception at run time. However, because of the special dynamic nature of the type loader, by
design it would not show any error at compile time.
WARNING This example is intended for reading only. It is not fully functional in the initial Gosu
community release due to in-progress changes in adding type loaders. Later versions of the Gosu
community release will include more APIs and documentation about creating your own custom type
loaders.
In this example, a function has an argument of the special type called Dynamic. The call to the function passes a
String object. This compiles successfully because the dynamic type allows any object to be assigned to it. As a
function parameter, within the function the parameter name value contains the object. The code then calls the
charAt method of the object. Normally, Gosu requires that the declared type contain explicit methods on the
object if you want to call them. In this case, the example type loader allows any method name on the Dynamic
object without compile errors. At run time, the type loader handles the method invocation and if the target object
at run time contains that method, it will succeed.
In this example, the charAt method is a method on a String object, so the code succeeds. If you changed the
code to call some arbitrary method name that String does not possess, such as notRealMethodName, this code
would throw an exception at run time. However, because of the special dynamic nature of the type loader, by
design it would not show any error at compile time.
WARNING This example is intended for reading only. It is not fully functional in the initial Gosu
community release due to in-progress changes in adding type loaders. Later versions of the Gosu
community release will include more APIs and documentation about creating your own custom type
loaders.
A Gosu program is a file with a .gsp file extension that you can run directly from a command-line tool. Addi-
tionally, you can run a Gosu program as the main file for a project in an IDE such as IntelliJ IDEA IDE. You can
run self-contained Gosu programs using the Gosu command line tool. The Gosu shell command-line tool encap-
sulates the Gosu language engine. You can run Gosu programs directly from the Windows command line as an
interactive session or run Gosu program files. You can optionally edit Gosu code with an included lightweight
Gosu editor implemented in Java. Using the graphic Gosu editor is a fast way to use the intelligent Gosu code
editor and run code without running a full IDE.
You might consider changing your system’s path to add the Gosu shell bin directory so you can simply type gosu
at the command line. On Windows, modify the systemwide Path variable by going to the Start menu and
choosing Control Panel System Environment Variables, and choose the Path variable. Add a semicolon and the full
path to the bin directory in the gosu shell directory.
For example, suppose you installed (copied) the Gosu shell directory to the path:
C:\gosu\
To test this, close any existing command prompt windows, then open a new command prompt window. Type the
following command:
gosu -help
Run a Gosu program. Include the .gsp file exten- filename gosu myfile
sion when specifying the file name.
Open the graphic Gosu editor, which can also run -g filename -g myfile
Gosu code. To open a file, include a filename
including the .gsp suffix. If you include no file-
name, the editor creates a new blank unsaved
program. Click Save As to save the file.
IMPORTANT: Using the graphic Gosu editor is a
fast way to use the intelligent Gosu code editor
and run code without running a full IDE.
Evaluate a Gosu expression on command line. -e expression gosu -e "new DateTime()"
Surround the entire expression with quote signs. -exec expression gosu -e """"a"""+"""b""""
For any quote sign in the expression, replace it
with three double-quote signs. For other special
DOS characters such as > and <, precede them
with a caret (^) symbol.
Add additional paths to the search path for Java -classpath path -classpath C:\gosu\projects\libs
classes or Gosu classes. Separate paths with
semicolons. If you are running a .gsp file, it is
often easier to instead use the classpath com-
mand within the .gsp file rather than this option.
For related information, see class loading infor-
mation in “Setting the Class Path to Call Other
Gosu or Java Classes” on page 60 and
“Advanced Class Loading Registry” on page 62.
Print help for this tool. -h -h
-help
4. Click Save As
5. Navigate to the directory you want to store the Gosu program and save the file as helloworld.gsp.
6. Quit the editor using the close box or the Quit menu item.
7. In a command prompt window, change the working directory to the directory with the file you created.
Note that the # in the meta line does not mean that the # symbol can start a line comments later on in Gosu
programs. The # character is not a valid line comment start symbol.
print (sum(10,4,7));
print (sum(222,4,3));
If it does not start with a "/" character, Gosu treats it as a relative path. The path is relative to the folder in
which the current program resides. This is the most common use. Use this feature to neatly encapsulate your
program and its supporting classes together in one location.
If the path starts with a "/" character, Gosu treats it as an absolute path.
You can include multiple paths in the same string literal using a comma character as a separator.
Typically you would place Java classes, Gosu classes, or libraries in subdirectories of your main Gosu program.
For example, suppose you have a Gosu program at this location:
C:\gosu\myprograms\test1\test.gsp
Copy your class file for the class mypackage.MyClass to the location:
C:\gosu\myprograms\test1\src\mypackage\MyClass.class
For this example, you would add classpath values with the following statement:
classpath "src,lib"
class Args {
// String argument
static var _name : String as Name
Note that the publicly-exposed property name is the symbol after the “as” keyword (in this case Name and
Hidden), not the private static variable itself. These are the names that are the options, although the case can vary,
such as: “-name jsmith” instead of “-Name jsmith”.
Choose a directory to save your command line tool. Create a subdirectory named src. Inside that create a subdi-
rectory called test (the package name). Save this Gosu class file as the file Args.gs in that src/test directory.
Next, run the following command
Paste in the following code for your program:
classpath "src"
uses gw.lang.cli.*
uses test.*
CommandLineAccess.initialize ( Args)
Click Save As and save this new command line tool as myaction.gsp in the directory two levels up from the
Args.gs file.
This outputs:
hello John
you are visible!!!!
One nice benefit of this approach is that these properties are available globally to all Gosu code as static proper-
ties. After initialization, all Gosu code can access properties merely by accessing the type (the class), without
pass a object instance to contain the properties.
Note that you can access the properties uncapitalized to better fit normal command line conventions.
The String property we define requires an argument value to follow the option. This is true of all non-boolean
property types. However, the boolean property does not require an argument value, and this type is special for
this reason. If a property is defined to have type boolean and the option is specified with no following value,
Gosu assumes the value true by default.
The properties can be any type to work with this approach, not merely String and boolean. However, there must
exist a Gosu coercion of the type from a String in order to avoid exceptions at run time. If no coercion exists, a
workaround is to add a writable property of type String,and add a read-only property that transforms that
String appropriately. This read-only property allows you to do whatever deserialization logic you would like, all
defined in Gosu.
Only properties defined with the modifiers public, static, writable properties on your command line class
participate in command line argument initialization.
If a user enters an incorrect option, CommandLineAccess.initialize() prints a help message and exits with a -1
return code. If you do not want this exit behavior, there is a secondary (overloaded) version of the initialize
method that you can use instead. Simply add the value false a second parameter to the method to suppress
exiting on bad arguments.
Annotation Description
@Required() This command line tool will not parse unless this property is included
@DefaultValue( String ) The default string value of this property.
@ShortName( String ) The short name of this option when used with a single-dash argument. For example, a
property named Day preceded by the annotation @ShortName( "d" ) allows the
option "-d" shortcut instead of “-day”. The short name works with the single-dash argu-
ment but not the double-dash variant.
For example:
package test
uses gw.lang.cli.*
class Args {
// String argument
@Required()
static var _name : String as Name
<common-service-init class="gw.internal.gosu.ShellKernelInit"/>
<classpath>
<entry>../lib</entry>
<entry>../gsrc</entry>
</classpath>
</serialization>
To add paths to the class path, add more <entry> elements containing class paths.
Or, simply run the tool from the command with no extra options to enter interactive mode:
gosu
The program will display a prompt that indicates that you are in the interactive shell rather than the command
prompt environment that called this tool.
gs >
You can then enter a series of Gosu expressions and statements, including defining functions and variables.
For example, you can type the following series of lines at the prompt:
gs > var s = new java.util.ArrayList() {1,2,3}
gs > s.each( \ o : Object -> print(o))
Type the command help to see all available commands in the interactive shell. Additional commands in the
interactive shell include the following:
Command Description
quit Quit the interactive shell.
exit Quit the interactive shell
ls Show a list of all defined variables
rm VARNAME remove a variable from interactive shell memory
clear clears (removes) all variables from interactive shell memory
If you enter a line of Gosu that necessarily requires additional lines, Gosu displays a different prompt (“...”) for
you to type the remaining lines. For example, if you type a statement block with an opening brace but no closing
brace, you can enter the remaining lines in the statement block. After you enter the line with the closing brace,
the shell returns to its regular prompt.
The shell provides code-completion using the TAB key. You must type at least one letter of a symbol, after which
you can type TAB and the shell will display various options. Note that package completion is not supported.
For example, type the following lines but do not press enter on the last line yet:
gs > var s = new java.util.ArrayList() {1,2,3}
gs > s.e
If you press TAB, the shell displays properties and methods that begin with the letter “e” and then redisplays the
current line you are typing:
each( block( java.lang.Object ):void ) eachWithIndex( block( java.lang.Object, int ):void )
elementAt( int ) ensureCapacity( int )
equals( java.lang.Object ) except( java.lang.Iterable<java.lang.Object> )
gs > s.e
Notes:
• Functions and blocks are supported in the interactive shell. However, defining new Gosu classes is not
supported in the interactive shell.
• The interactive shell is different from the standard in option for the tool, which may be appropriate for some
purposes. You can define the output of one tool to be in Gosu and then redirect (pipe) the contents of that tool
into the Gosu shell, using the hyphen option.
Is Windows
Call the gw.util.Shell.isWindows() method to determine if the current host system is Windows-based.
Gosu Types
This topic describes the Gosu-supported data types and how to use each one. For more information about manip-
ulating types or examining type information at run time, see “Type System” on page 251.
This topic includes:
• “Built-in Types” on page 65
• “Access to Java Types” on page 72
• “Arrays” on page 72
• “Object Instantiation and Properties” on page 74
• “Numeric, Binary, and Hex Literals” on page 76
Built-in Types
Gosu supports the following native data types:
• Array • Number
• Boolean • Object
• DateTime • String
• Type
Array
An array is a collection of data values, with each element of the array associated with a number or index.
Example values for the Array data type are:
• Array[] • Number[]
• Boolean[] • Object[]
• DateTime[] • String[]
Alternatively, you can use an associative array, which uses a String value as the index instead of a number.
Instead of accessing an array element directly through its index number, you access it with a string value that has
been set to an index value. Associative arrays are useful if an index value is not known at compile time, but can
be determined at run time, as with user-entered data, for example.
myValue = Claim["ClaimNumber"]
Associative arrays have some similarities to the Java language Map, which is also supported in Gosu.
For more information creating and using arrays, see “Arrays” on page 72.
For more information about special Gosu APIs related to using lists, maps, and other collections in Gosu, see
“Collections” on page 183.
Boolean
Gosu contains two types that can contain the values true and false:
• A primitive type called boolean that corresponds to Java’s primitive boolean type. Possible values for vari-
ables declared to the Boolean data type are:
• true
• false
• A Gosu Boolean type that is a boxed type, which means it is a class wrapper around a primitive boolean
value. Possible values for variables declared to the Boolean data type are:
• true
• false
• null
For both boolean and Boolean, some other values can coerce to true or false. For example, the following
values coerce to true:
• the number 1
• the String value with data "true" (see the following discussion)
The following values coerce to false:
• the number 0
• the String value with data "false" or any other value other than "true" (see the following discussion).
It is important to note the value null is not the same as false and coercions for this value work differently
between the two types. Variables and properties with the Boolean type can have a value of null, where null
means “I do not know” or “unstated” in addition to true and false. However, variables and properties with the
boolean type cannot have a value of null, and can only coerce to true or false.
IMPORTANT For important information about primitives and comparisons of boxed and unboxed
types in Gosu, see “Working with Primitive Types” on page 258.
Example
var hasMoreMembers == null
var isDone = false
DateTime
DateTime data types involve, as the name suggests, values that are either calendar dates or time (clock) values, or
both. The following table lists possible formats for the DateTime data type.
Format Example
MMM d, yyyy Jun 3, 2005
MM/dd/yy 10/30/06
MM/dd/yyyy 10/30/2006
MM/dd/yy hh:mm a 10/30/06 10:20 pm
yyyy-MM-dd HH:mm:ss.SSS 2005-06-09 15:25:56.845
yyyy-MM-dd HH:mm:ss 2005-06-09 15:25:56
yyyy-MM-dd'T'HH:mm:ssz 2005-06-09T15:25:56 -0700
EEE MMM dd HH:mm:ss zzz yyyy Thu Jun 09 15:24:40 GMT 2005
Character Meaning
a AM or PM (determined from 24-hour clock)
d day
E Day in week (abbreviation)
h hour (24 hour clock)
m minute
M month
s second
S fraction of a second
T parse as time (ISO8601)
y year
z Time Zone offset (GMT, PDT, and so on)
If you do not specify the time (as in "October 31, 2002"), then Gosu sets the implied time to 12:00 a.m. of that
day. Use the built-in Gosu gw.api.util.DateUtil.* library functions to work with DateTime objects. There are
methods to add a certain number of days, weekdays, weeks, or months to a date. There is a method to remove the
time element from a date (trimToMidnight). Type gw.api.util.DateUtil into the Gosu Tester, and then press
period to see the full list of methods.
Example
var diff = gw.api.util.DateUtil.daysBetween( "Mar 5, 2006", gw.api.util.DateUtil.currentDate() )
Gosu implicitly coerces the Gosu DateTime object from String in most formats. For example:
var date : DateTime = "2007-01-02"
Number
The Number data type represents all numbers, including integers and floating-point values. Gosu supports the
standard Java number types of double, float, int, long, and short. (See “Primitive Types” on page 71.)
Possible values for the Number data type are:
• 1
• 246
• 3.14159
• NaN
• Infinity
• null
• "9.2"
IMPORTANT For more information about primitives and comparisons of boxed and unboxed types in
Gosu, see “Working with Primitive Types” on page 258.
Scientific Notation
Gosu supports the use of scientific notation to represent large or small numbers. Scientific notation represents a
number as a coefficient (a number greater than or equal to 1 and less than 10) and a base (which is always 10).
For example, consider the following number:
1.23 x 1011
The number 1.23 is the coefficient. The number 11 is the exponent, which means the power of ten. The base
number 10 is always written in exponent form. Gosu represents the base number as the letter “e”, which stands
for “exponent”.
You must enclose a number written in scientific notation within quotation marks, such as "2.057e3", for Gosu to
understand the number.
Examples
var PI= 3.14
var count = 0
var result1 = "9.2" * 3
var result2 = "2.057e3" * PI
//Result
result1 = 27.599999999999998
result2 = 6458.9800000000005
Object
An object encapsulates some data (variables and properties) and methods (functions).
Internally, an object has an intrinsic type that encapsulates the underlying data source. Gosu connects directly
with a variety of data sources through intrinsic types. Java classes are represented internally through a Java
intrinsic type that bridges Gosu with Java classes.
Examples
var a : Address
var map = new java.util.HashMap()
For more information creating and using objects, see “Object Instantiation and Properties” on page 74.
For more information about the Gosu type system, see “Type System” on page 251.
String
Gosu treats strings as a sequence of characters. You create a string by enclosing a string of characters in begin-
ning and ending double-quotation marks. Possible values for the String data type are:
• "homeowners"
• "auto"
• ""
Whether the variable holds an empty String or null, the method returns false as expected.
This prints:
cat
String Utilities
You can access additional String methods in API library gw.api.util.StringUtil. Type
gw.api.util.StringUtil into the Gosu Tester and press period to see the full list of methods.
Sequence Result
\\ Inserts a backslash into the string without forcing an escape sequence.
\" Inserts a double-quotation mark into the string without terminating it.
Note: This does not work inside embedded code within Gosu templates. In such cases, do not escape
the double quote characters. See “Gosu Templates” on page 243.
\n Inserts a new line into the string so that the remainder of the text begins on a new line if printed.
\t Inserts a tab into the string to add horizontal space in the line if printed.
Examples
Claim["ClaimNumber"]
var address = "123 Main Street"
"LOGGING: \n\"Global Activity Assignment Rules\""
For example, suppose you need to display text with some calculation in the middle of the text:
var mycalc = 1 + 1
var s = "One plus one equals " + mycalc + "."
Instead of this multiple-line code, embed the calculation directly in the String as a template:
var s = "One plus one equals ${ 1 + 1 }."
However, Gosu provides an alternative template style. Use the three-character text <%= to begin the expression.
Use the two-character text %> to end the expression. For example, you can rewrite the previous example as the
following concise code:
var s = "One plus one equals <%= 1 + 1 %>."
print("one")
var s = "Hello. <% print("two") %>We will go to France<% print("three") %>."
print(s)
Within a code expression, do not attempt to escape double quote characters inside templates using the special
syntax for quote characters in String values. In other words, the following is valid Gosu code:
var s= "<% var myvalue = {"a", "b"} %>"
However, the following is invalid due to improper escaping of the internal double quotes:
var foo = "<% var bar = {\"a\", \"b\"} %>"
For much more information about Gosu templates, see “Gosu Templates” on page 243.
Type
The Type data type is a meta-type. It is the “type” of types. If you get the type of something using the typeof
keyword, the type of the result is Type.
Examples of types
Array
DateTime
Number
String
Type
int
java.util.List[]
For more information about using Type objects to get information about a type, see “Type System” on page 251.
Note the following aspects of types:
• Everything has a type. All Gosu values have a type.
• Language primitives have types. For example the code “typeof 29” is valid Gosu, and it returns
java.lang.Integer, which is a Type. In other words, Integer is a subtype of Type.
• Object instances have types. The type of an instance of a class is the class itself.
• Even types have types. Because everything has a type, you can use typeof with Type objects also.
IMPORTANT For more information about the Type class and the typeof keyword how to use it, see
“Basic Type Checking” on page 252.
Primitive Types
Gosu supports the following Primitive types for compatibility with Java language primitives.
IEEE 754 is the IEEE (Institute of Electrical and Electronics Engineers) standard for Binary Floating-Point
Arithmetic. For more information, see the following: http://en.wikipedia.org/wiki/IEEE_754.
From Gosu you can also use boxed versions (non-primitive versions) of these primitive types defined for the
Java language, in the java.lang package.
IMPORTANT For important information about primitives and comparisons of boxed and unboxed
types in Gosu, see “Working with Primitive Types” on page 258.
Arrays
As described previously (“Gosu Types” on page 65), an array can be either indexed or associative.
• Indexed arrays use an index number to access an array member.
• Associative arrays are like maps of strings to values. They are only arrays in the sense that you can access
elements of the map using array notation dynamically.
If you create an array, you must explicitly define the size of the array or implicitly define the size by simultane-
ously defining the array elements. For example:
// arrays of strings
var s1 = new String[4]
var s2 = new String[ ] {"This", "is", "a", "test."}
// arrays of integers
var a1 = new int[3]
var a2 = new int[] {1,2,3}
var a3 : int[] = {1,2,3}
Syntax
<expression>[<index value>]
<expression>[<associative value>]
Examples
Expression Result
Claim.Exposures[0] An exposure
gw.api.util.StringUtil.splitWhitespace( "a b c d e" )[2] "c"
You can also iterate through the members of an array using the for() construction. See “Iteration in For() State-
ments” on page 103 for details.
You can also create a new array with a default value for each item using an included Gosu enhancement on the
Arrays object. Call the makeArray method and pass it a default value and the size of the array. Gosu uses the type
of the object to type the array.
For example, create an array of 10 items initialized to the Boolean value false with the code:
var x = Arrays.makeArray( false, 10 )
Be aware that in situations it may be more appropriate to use collections such as List or Map than to use arrays.
Collections such as List or Map are inherited from the Java language but have additional enhancement methods
in Gosu.
IMPORTANT Consider using collections instead of arrays to take advantage of some advanced
features of Gosu. For more information about special Gosu APIs for lists, maps, and other collections
in Gosu, see “Collections” on page 183.
Example
var list = new java.util.ArrayList()
In some situations, it may be more appropriate to use collections such as List or Map rather than to use arrays.
The List and Map classes inherit from the Java language and Gosu adds additional enhancement methods. For
more information about special Gosu APIs related to using lists, maps, and other collections in Gosu, see
“Collections” on page 183.
Array Expansion
Gosu supports an operator that expands arrays and lists: the *. operator. For more information, see “List and
Array Expansion (*.)” on page 187.
Syntax
<object-property-path> = <expression>
However, properties can be write-protected (as well as read-protected). For example, the following Gosu code:
Activity.UpdateTime = "Mar 17, 2006"
Example
myObject.Prop = "Test Value"
var startTime = myObject.UpdateTime
Syntax
<expression>.<property>
Examples
Expression Result
Claim.Contacts.Attorney.Name Some Name
Claim.Addresses.State New Mexico
the addition of parenthesis at the end to denote the function. Gosu uses the dot notation to call a method on a
object instance.
For more details about how Gosu handles null values in the expression to the left of the period, see “Handling
Null Values In Expressions” on page 95.
Syntax
expression.METHOD_NAME()
Example
Expression Result
claim.isClosed() Return a Boolean value indicating the status of Claim
claim.resetFlags() Reset flags for this claim
See “Static Method Calls” on page 94 for more details. See also “Using Reflection” on page 256 for regarding
using type information to determine methods of an object.
Syntax
OBJ[PROPERTY_NAME]
Array access uses late binding to avoid potential compile-time errors. For example, suppose that you have an
instance of a general type, say Object, as a function argument:
function getDisplayName( obj : Object) {
var name : String
name = obj.DisplayName // Compile error - no DisplayName property on Object
name = obj["DisplayName"] // Ok, so long as there is a DisplayName property at runtime
}
The only requirement is that object’s type have a property called DisplayName. There is no base interface that all
the arguments implement. The only way to access the DisplayName property without a compile-time error is
through “late binding” as with associative array access.
In this example, if the function caller passes an object parameter that does not have a DisplayName property, at
run time Gosu throws an exception.
Examples
In addition to being able to read an associative array member, you can write to an associative array member as
well. For example:
var address : Address
var city = address["City"]
address["City"] = "San Mateo"
The following table lists the suffix or prefix for different numeric, binary, and hexadecimal literals.
Type Syntax
byte 'b' or 'B' suffix var aByte = 1b
This topic describes the basic Gosu operators and expressions in the language.
This topic includes:
• “Gosu Operators” on page 77
• “Standard Gosu Expressions” on page 79
• “Arithmetic Expressions” on page 79
• “Equality Expressions” on page 82
• “Evaluation Expressions” on page 84
• “Existence Testing Expressions” on page 84
• “Logical Expressions” on page 84
• “New Object Expressions” on page 86
• “Relational Expressions” on page 89
• “Unary Expressions” on page 91
• “Importing Types and Package Namespaces” on page 92
• “Conditional Ternary Expressions” on page 93
• “Special Gosu Expressions” on page 94
• “Handling Null Values In Expressions” on page 95
Gosu Operators
Gosu uses standard programming operators to perform a wide variety of mathematical, logical, and object
manipulation operations. If you are familiar with the C, C++ or Java programming languages, you might find
that Gosu operators function similar to those other languages. Gosu evaluates operators within an expression or
statement in order of precedence. (For details, see “Operator Precedence” on page 78.)
Gosu operators take either a single operand (unary operators), two operands (binary operators), or three operands
(a special case ternary operator). The following list provides examples of each operator type:
unary 1 • -3
• typeof “Test”
• new Array[3]
binary 2 • 5 - 3
• a and b
• 2 * 6
Operator Precedence
The following list orders the Gosu operators from highest to lowest precedence. Gosu evaluates operators with
the same precedence from left to right. The use of parentheses can modify the evaluation order as determined by
operator precedence. Gosu first evaluates an expression within parentheses, then uses that value in evaluating the
remainder of the expression.
Operator Description
. Property access, array indexing, function calls and expression grouping. The
[ ] operators with the question marks are the null-safe operators. See “Handling
( )
Null Values In Expressions” on page 95.
?.
?[]
?:
new Object creation, object reflection
, Array value list, as in {value1, value2, value3}
Argument list, as in (parameter1, parameter2, parameter3)
as As, typeas
typeas
+ Unary operands (positive, negative values)
-
~ Bit-wise OR, logical NOT, typeof, eval(expression)
!
not
typeof
eval
typeis Typeis
* Multiplication, division, modulo division
/
%
<< Bitwise shifting
>>
>>>
+ Addition, subtraction, string concatenation. The versions with the question
- marks are the null-safe versions (see “Null-safe Math Operators” on page 96).
?+
?-
< Less than, less than or equal, greater than, greater than or equal
<=
>
>=
== Equality, inequality. For general discussion and also comparison of == and
=== ===, see “Equality Expressions” on page 82.
!=
<>
& bitwise AND
Operator Description
^ bitwise exclusive OR
| bitwise inclusive OR
&& Logical AND, the two variants are equivalent
and
|| Logical OR, the two variants are equivalent
or
? : Conditional (ternary, for example, 3*3 == 9 ? true : false)
= += -= *= Assignment operator statements. These are technically Gosu statements, not
/= %= &= expressions. For more information, see “Gosu Variables” on page 98.
^= |= <<=
>>= >>>=
Arithmetic Expressions
Gosu defines arithmetic expressions corresponding to all the common arithmetic operators, which are:
• Addition and Concatenation Operator (+)
• Subtraction Operator (-)
• Multiplication Operator (*)
• Division Operator (/)
• Arithmetic Modulo Operator (%)
Gosu supports Java big decimal arithmetic on the +, -, *, /, and % arithmetic operators. Thus, if the left- or right-
hand side of the operator is a Java BigDecimal or BigInteger, then the result is Big also. This can be especially
important if considering the accuracy, such as usually required for currency figures.
• If either operand is a String, Gosu converts the non-String operand to a String. The result is the concatena-
tion of the two strings.
Expression Result
3 + 5 8
8 + 7.583 15.583
"Auto" + "Policy" "AutoPolicy"
10 + "5" "105"
"Number " + 1 "Number 1"
For the null-safe version of this operator, see “Null-safe Math Operators” on page 96.
Expression Result
9 - 2 7
8 - 3.359 4.641
"9" - 3 6
For the null-safe version of this operator, see “Null-safe Math Operators” on page 96.
Expression Result
2 * 6 12
12 * 3.26 39.12
"9" * "3" 27
For the null-safe version of this operator, see “Null-safe Math Operators” on page 96.
Expression Result
10 / 2 5
5 / "2" 2.5
5 / “test” NaN
1/0 Infinity
0/0 NaN
0/1 0
For the null-safe version of this operator, see “Null-safe Math Operators” on page 96.
Expression Result
10 % 3 1
2 % 0.75 0.5
For the null-safe version of this operator, see “Null-safe Math Operators” on page 96.
For example, 10 << 1 evaluates to 20. The decimal number 10 is 01010 binary. In binary, this code does a binary
bitwise left shift of 01010 one bit to the left. The result is binary 10100, which is decimal 20.
The expression 10 << 2 evaluates to 40. The decimal number 10 is 001010 binary. In binary, this code does a
binary bitwise left shift of 001010 one bit to the left. The result is binary 101000, which is decimal 40.
IMPORTANT For signed values, the >> operator automatically sets the high-order bit with its previous
value for each shift. This preserves the sign (positive or negative) of the result. For signed integer
values, this is the usually the appropriate behavior. Contrast this with the >>> operator.
For example, 10 >> 1 evaluates to 5. The decimal number 10 is 1010 binary. In binary, this code does a binary
bitwise right shift of 1010 one bit to the right. The result is binary 0101, which is decimal 5.
The expression -10 >> 2 evaluates to -3. The decimal number -10 is 11111111 11111111 11111111 11110110
binary. This code does a binary bitwise right shift two bits to the right, filling in the top sign bit with the 1
because the original number was negative. The result is binary 11111111 11111111 11111111 11111101, which is
decimal -3.
IMPORTANT The >>> operator sets the high-order bit with its previous value for each shift to zero.
For unsigned integer values, this is the usually the appropriate behavior. Contrast this with the >> oper-
ator.
Equality Expressions
Equality expressions return a Boolean value (true or false) indicating the result of the comparison between the
two expressions. Equality expressions consist of the following types:
• == Operator
• != or <> Operator
== Operator
The == operator tests for relational equality. The operands can be of any compatible types. The result is always
Boolean. For reference types, Gosu language, the == operator automatically calls object.equals() to compare
values. To compare whether the two operands are the same in-memory object, use the === operator instead. See
“=== Operator Compares Object Equality” on page 83 for details.
Syntax
a == b
Examples
Expression Result
7 == 7 true
Expression Result
"3" == 3 true
3 == 5 false
!= or <> Operator
The “!=” or “<>” operator tests for relational inequality. The operands can be of any compatible types. The result
is always Boolean. See also the examples in “Logical NOT” on page 85 for another use of the != operator.
Syntax
a != b
a <> b
Examples
Expression Result
7 != 7 false
Expression Result
"3" <> 3 false
3 <> 5 true
Evaluation Expressions
The eval() expression evaluates Gosu source at runtime, which enables dynamic execution of Gosu source
code. Gosu executes the source code within the same scope as the call to eval().
Syntax
eval( <expression> )
Examples
Expression Result
eval( "2 + 2" ) 4
eval( 3 > 4 ? true : false ) false
Syntax
exists ( [var] identifier in expression1 [index identifier] where expression2 )
The index variable identifier iterates through all possible array index values. The result is the type Boolean.
The expression returns true to indicate success (such an element exists), or returns false if no such desired
expression exists.
Logical Expressions
Gosu logical expressions use standard logical operators to evaluate the expression in terms of the Boolean values
of true and false. Most often, logical expressions include items that are explicitly set to either true or false or
evaluate to true or false. However, they can also include the following:
• Number values (both positive and negative numbers, regardless of their actual value) and the String value
"true", coerce to true if used with Boolean operators.
• String values other than the value "true", which all coerce to false if used with Boolean operators
• the Number 0, which coerces to false if used with Boolean operators
• the value null, which coerces to false if used with Boolean operators.
IMPORTANT For important differences between Boolean and boolean types and differences in coer-
cion, see “Boolean” on page 66.
• Logical OR
• Logical NOT
As logical expressions are evaluated from left to right, they are tested for possible short-circuit evaluation using
the following rules:
• true OR any-expression always evaluates to true. Gosu only runs and evaluates any-expression if the
expression before the AND is true. So, if Gosu determins the expression before the AND evaluates to true, the
following expression is not evaluated.
• false AND any-expression always evaluates to false. Gosu only runs and evaluates any-expression if the
expression before the AND is true. So, if Gosu determins the expression before the AND evaluates to false,
the following expression is not evaluated.
Logical AND
Gosu uses either and or && to indicate a logical AND expression. The operands must be of the Boolean data type
(or any type convertible to Boolean). The result is always Boolean.
Syntax
a and b
a && b
Examples
Expression Result
(4 > 3) and (3 > 2) (true/true) = true
(4 > 3) && (2 > 3) (true/false) = false
(3 > 4) and (3 > 2) (false/true) = false
(3 > 4) && (2 > 3) (false/false) = false
Logical OR
Gosu uses either or or || to indicate a logical OR expression. The operands must be of the Boolean data type (or
any type convertible to Boolean). The result is always Boolean.
Syntax
a or b
a || b
.
Examples
Expression Result
(4 > 3) or (3 > 2) (true/true) = true
(4 > 3) || (2 > 3) (true/false) = true
(3 > 4) or (3 > 2) (false/true) = true
(3 > 4) || (2 > 3) (false/false) = false
Logical NOT
To indicate a logical negation (a logical NOT expression), use either the keyword not or the exclamation point
character (!), also called a bang. The operand must be of the Boolean data type or any type convertible to
Boolean. The result is always Boolean.
Syntax
not a
!a
Examples
Expression Result
!true false
not false true
!null true
not 1000 false
The following examples illustrate how to use (or not use) the NOT operator.
• Bad example. The following is a bad example of how to use the logical NOT operator.
if (not PolicyLine.BOPLiabilityCov.Limit ==
PolicyLine.PolicyPeriod.MostRecentPriorBoundRevision.BOPLine.BOPLiabilityCov.Limit) {
return true
}
This example causes an error if it runs because Gosu associates the NOT operator with the variable to its right
before it evaluates the expression. In essence, the expression becomes:
if (false == PolicyLine.PolicyPeriod.MostRecentPriorBoundRevision.BOPLine.BOPLiabilityCov.Limit)
which causes a class cast exception during the comparison, as follows:
'boolean (false)' is not compatible with Limit
• Better example. The following is a better example of how to use the NOT operator.
if (not (PolicyLine.BOPLiabilityCov.Limit ==
PolicyLine.PolicyPeriod.MostRecentPriorBoundRevision.BOPLine.BOPLiabilityCov.Limit)) {
return true
}
In this example, the extra parentheses force the desired comparison, then associate the NOT operator with it.
• Preferred example. Use the following approach for writing code of this type.
if (PolicyLine.BOPLiabilityCov.Limit !=
PolicyLine.PolicyPeriod.MostRecentPriorBoundRevision.BOPLine.BOPLiabilityCov.Limit) {
return true
}
As can be seen, there was no actual need to use the NOT operator in this expression. The final code expression
is somewhat simpler and does exactly what is asked of it.
Typeis Expressions
Gosu uses the operator typeis to test type information of an object. For more information, see “Basic Type
Checking” on page 252.
If you pass arguments to the new operator, Gosu passes those arguments to the constructor. There might be
multiple constructors defined, in which case Gosu uses the types and numbers of objects to choose which
constructor to call.
Examples
Expression Result
new java.util.HashMap(8) Creates an instance of the HashMap Java class.
new String[12] Creates a String array with 12 members with no initial values.
new String[] { "a", "b", "c" } Creates a String array with three members, initialized to "a", "b", and "c".
Optionally Omit Type Name with ‘new’ When Type is Determined From Context
If the type of the object is determined from the programming context, you can omit the type name entirely in the
object creation expression with the new keyword.
For example, first declare a variable to a specific type. Next, assign that variable a new object of that type in a
simple assignment statement that omits the type name:
// declare variable explicitly with a type
var s : String
You can also omit the type name if the context is a method argument type:
class SimpleObj {
}
class Test {
function doAction ( arg1 : SimpleObj ) {
}
}
The following is a more complex example using both local variables and class variables:
class Person {
private var _name : String as Name
private var _age : int as Age
}
class Tutoring {
private var _teacher : Person as Teacher
private var _student : Person as Student
}
// declare a variable as a specific type to omit the type name in the "new" expression
// during assignment to that variable
var p : Person
var t : Tutoring
p = new() // notice the type name is omitted
t = new() // notice the type name is omitted
// if a class var or other data property has a declared type, optionally omit type name
t.Teacher = new()
t.Student = new()
// optionally OMIT 'new' keyword and still use the Gosu initialization syntax
t.Student = { :Name = "Bob Smith", :Age = 30 }
Omitting the new keyword can improve readability of creating XML objects when using XSD-based types. Types
imported from XSDs sometimes have complex and hard to read type names.
For more information about object initializer syntax, see “Object Initializer Syntax” on page 88
The syntax is simple: after a constructor, open a curly brace and then add pairs of property name equals values,
followed by a close brace. After a constructor, open a curly and then add pairs of property name equals values.
Each name/value pair has the following syntax:
:PROPERTY_NAME = VALUE
Notice that the property name has a colon before it. For multiple properties, separate multiple name/value pairs
by commas.
For example, suppose you have the following code:
var myFileContainer = new my.company.FileContainer()
myFileContainer.DestFile = jarFile
myFileContainer.BaseDir = dir
myFileContainer.Update = true
myFileContainer.WhenManifestOnly = ScriptEnvironment.WHEN_EMPTY_SKIP
Instead, you can use object initializers to simplify this code to the following:
var myFileContainer = new my.company.FileContainer() { :DestFile = jarFile, :BaseDir = dir,
:Update = true, :WhenManifestOnly = ScriptEnvironment.WHEN_EMPTY_SKIP }
Another case where this syntax is useful is naturally expressing a nested object tree, such as XML data.
For example, suppose you have the following code:
using xsd.test.*
simpleTest.test2s.add(test2)
simpleTest.test2s.add(new Test2())
simpleTest.test2s.get(1).final = true
simpleTest.test2s.get(1).Test1 = new TestType()
simpleTest.test4s.add(test1)
simpleTest.test3 = Blue // Since this is a simple child element, you access its value directly
return simpleTest.toXML()
return simpleTest.toXML()
The object initializer syntax more clearly expresses the nested nature of the XML nodes, clarifying what the
generated XML looks like.
Relational Expressions
Gosu relational operators support all types of objects that implements the java.lang.Comparable interface, not
just numbers. Relational expressions return a Boolean value (true or false) indicating the result of a compar-
ison between two expressions. Relational expressions consist of the following types:
• > Operator
• >= Operator
• < Operator
• <= Operator
It is possible to string together multiple relatational operators to compare multiple values. Add parenthesis
around each individual expression. For example, the following expression ultimately evaluates to true:
( (1 <= 2) <= (3 > 4) ) >= (5 > 6)
The first compound expression evaluates to false ( (1 <= 2) <= (3 > 4) ) as does the second expression ( 5 >
6 ). However, the larger expression tests for greater than or equal. Therefore, as false is equal to false, the
entire expression evaluates to true.
> Operator
The “>” operator tests two expressions for a “greater than” relationship. The operands can be either Number,
String, or DateTime data types. The result is always Boolean.
Syntax
expression1 > expression2
Examples
Expression Result
8 > 8 false
"zoo" > "apple" true
5 > "6" false
currentDate > policyEffectiveDate true
>= Operator
The “>=” operator tests two expressions for a “greater than or equal” relationship. The operands can be either
Number, String, or DateTime data types. The result is always Boolean.
Syntax
expression1 >= expression2
Examples
Expression Result
8 >= 8 true
"zoo" >= "zoo" true
5 >= "6" false
currentDate >= policyEffectiveDate true
< Operator
The “<” operator tests two expressions for a “less than” relationship. The operands can be either Number, String,
or DateTime data types. The result is always Boolean.
Syntax
expression1 < expression2
Examples
Expression Result
8 < 5 false
"zoo" < "zoo" false
5 < "6" true
currentDate < policyEffectiveDate false
<= Operator
The “<=” operator tests two expressions for a “less than or equal to” relationship. The operands can be either
Number, String, or DateTime data types. The result is always Boolean.
Syntax
expression1 <= expression2
Examples
Expression Result
8 <= 5 false
"zoo" <= "zoo" true
5 <= "6" true
currentDate <= policyEffectiveDate false
Unary Expressions
Gosu supports the following unary (single operand) expressions:
• Numeric Negation
• Typeof Expressions
• Importing Types and Package Namespaces
• Bit-wise NOT
The following sections describe these expressions. The value of a typeof expression cannot be fully determined
at compile time. For example, an expression at compile time might resolve as a supertype. At runtime, the
expression may evaluate to a more specific subtype.
Numeric Negation
Gosu uses the “-” operator to indicate numeric negation. The operand must be of the Number data type. The result
is always a Number.
Syntax
-value
Examples
Expression Result
-42 -42
-(3.14 - 2) -1.14
Typeof Expressions
Gosu uses the operator typeof to determine meta information about an expression’s type. The operand can be
any valid data type. The result is the type of the expression. For more information, see “Basic Type Checking” on
page 252.
Bit-wise NOT
The bit-wise NOT operator treats a numeric value as a series of bits and inverts them. This is different from the
logical NOT operator (! — the exclamation point), which treats the entire numeral as a single Boolean value. In
the following example, the logical NOT operator assigns a Boolean value of true to x if y is false, or false if y
is true:
x = !y
However, in the following example, the bit-wise NOT operator (~ — the tilde) treats a numerical value as a set of
bits and inverts each bit, including the sign operator. For example, the decimal number 7 is the binary value 0111
with a positive sign bit. If you use the bit-wise NOT, the expression ~7 evaluates to the decimal value -8. The
binary value 0111 reverses to 1000 (binary value for 8), and the sign bit changes as well to -8.
Use the bit-wise NOT operation to manipulate a bit mask. A bit mask is a technique in which number or byte field
maintains the state of many items where flags map to each binary digit (bit) in the field.
Syntax
After the uses operator, specify a package namespace or a specific type such as a fully-qualified class name:
uses type
uses namespace
Namespaces can be specified with an asterisk (*) character to indicate a hierarchy, such as:
uses toplevelpackage.subpackage.*
Example 1
The following code uses a fully-qualified type name:
var map = new java.util.HashMap()
Instead, you can use the following code that declares an explicit type with the uses operator:
// This "uses" expression...
uses java.util.HashMap
// Use this simpler expression without specifying the full package name:
var map = new HashMap()
Example 2
The following code uses a fully-qualified type name:
var map = new java.util.HashMap()
Instead, you can use the following code that declares a package hierarchy with the uses operator:
// This "uses" expression...
uses java.util.*
// Use this simpler expression without specifying the full package name:
var map = new HashMap()
IMPORTANT Explicit types always have precedence over wildcard namespace references. This is
different compared to the behavior of the Java import operator.
Syntax
expression ? result-if-true : result-if-false
Gosu runs and evaluates the first expression expr1 if and only if the condition expressions evaluates to true.
Likewise, Gosu runs and evaluates the second expression expr2 if and only if condition evaluates to false.
Examples
Expression Result
3 > 4 ? true: false false
3*3 == 9 ? true : false true
The type of the result is the type lowest down in the type hierarchy to the types of both clauses. If either clause is
a primitive type such as int or boolean, Gosu coerces the primitive type to its boxed (subclass of Object)
version before doing this change. For example, boolean coerces to Boolean.
If they have no ancestors in common, the compile-time type of the result is Object. This is important to note,
because it may affect the coercions you do with the result and what properties or methods you call on the result.
Note: Although the compile-time type looks at both types to find a common ancestor in the type hierarchy,
a ternary clause does not cause the creation of a Gosu compound type. For a more detailed explanation of
this special type, see “Compound Types” on page 260
Function Calls
This expression calls a function with an optional list of arguments and returns the result.
Syntax
<function-name>( <argument-list> )
Examples
Expression Result
now() Current Date
concat( "limited-", "coverage" ) "limited-coverage"
Syntax
<type-expression>.<static-method-name>( <argument list> )
Examples
Expression Result
Person.isAssignableFrom( type ) true/false
java.lang.System.currentTimeMillis() Current time
java.util.Calendar.getInstance() Java Calendar
For more information about static methods and the static operator, see “Modifiers” on page 135
Syntax
<type-expression>.<static-property>
Examples
Expression Result
Claim.TypeInfo Claim typeInfo
java.util.Calendar.FRIDAY Friday value
For more information about static properties in classes, see “Modifiers” on page 135.
Although the variable called result has the value null, the code does not throw any exception. If you use the
regular period operator instead, Gosu throws a null pointer exception.
For example, suppose there is a variable str of type String. At run time the value contains either a String or
null. Perhaps you want to pass the input to a display routine. However, if the value of str is null, you want to
use a default value rather than null. Use the ?: operator as follows:
var result = str ?: "(empty)" // return str, but if the value is null return a default string
If the value to the left of the question mark is null, the entire expression for the operator returns null. If the left-
hand-operand is not null, Gosu looks inside the index subexpression and evaluates it and indexes the array, list
or map. Finally, Gosu returns the result, just like the regular use of the angled brackets for indexing lists, arrays,
and maps.
Statements
This topic describe important concepts in writing more complex Gosu code to perform operations required by
your business logic.
This topic includes:
• “Gosu Statements” on page 97
• “Gosu Variables” on page 98
• “Gosu Conditional Execution and Looping” on page 102
• “Gosu Functions” on page 106
Gosu Statements
A Gosu expression has a value, while Gosu statements do not. Between those two choices, if it is possible to pass
the result as an argument to a function, then it is an expression. If it is not possible, then it is a statement.
For example, the following are all Gosu expressions as each results in a value:
5 * 6
typeof 42
exists ( var e in Claim.Exposures where e == null )
Note: Do not confuse statement lists with expressions or Gosu blocks. Blocks are anonymous functions that
Gosu can pass as objects, even as objects passed as function arguments. For more information, see “Gosu
Blocks” on page 165.
Statement Lists
A statement list is a list containing zero or more Gosu statements beginning and ending with curly braces “{” and
“}”, respectively.
Chapter 6, Statements 97
Gosu Reference Guide
It is the Gosu standard always to omit semicolon characters in Gosu at the end of lines. Code is more readable
without optional semicolons. In the more rare cases in which you type multiple statement lists on one line, such
as within block definitions, use semicolons to separate statements. For other style guidelines, see “General
Coding Guidelines” on page 279.
Syntax
{ statement-list }
print( y )
}
Gosu Variables
To create and assign variables, consider the type of the variable as well as its value.
• Variable Type Declaration
• Variable Assignment
Syntax
var identifier [ : type-literal ] = expression
var identifier : type-literal [ = expression ]
Examples
var age = 42
var age2 : Number
var age3 : Number = "42"
var c : Claim
...
Variable Assignment
Gosu uses the standard programming assignment operator = to assign the value on the right-side of the statement
to the item on the left-side of the statement.
Syntax
variable = expression
Examples
count = 0
time = now()
98 Chapter 6, Statements
Gosu Reference Guide
Gosu also supports compound assignment operators that perform an action and assign a value in one action. The
following lists each compound operator and its behavior. The examples assume the variables are previous
declared as int values.
Chapter 6, Statements 99
Gosu Reference Guide
However, the following Gosu is invalid because statements are impermissible in an expression, which Gosu
requires in a while statement:
while(i++ < 10) { // Compilation error!
print( i )
}
It is important to understand that Gosu supports the increment and decrement operator only after a variable, not
before a variable. In other words, i++ is valid but ++i is invalid. The ++i form exists in other languages to
support expressions in which the result is an expression that you pass to another statement or expression. As
mentioned earlier, in Gosu these operators do not form an expression. Thus you cannot use increment or decre-
ment in while declarations, if declarations, and for declarations. Because the ++i style exists in other languages
to support forms that are unsupported in Gosu, Gosu does not support the ++i form of this operator.
IMPORTANT Gosu supports the ++ operator after a variable, such as i++. Using it before the variable,
such as ++i is unsupported and generates compiler errors.
Syntax
if ( <expression> ) <statement>
[ else <statement> ]
Example
if( a == b ) { print( "a equals b" ) }
To improve the readability of your Gosu code, Gosu automatically downcasts after a typeis expression if the
type is a subtype of the original type. This is particularly valuable for if statements and similar Gosu structures.
Within the Gosu code bounded by the if statement, you do not need to do casting (as TYPE expressions) to that
subtype. Because Gosu confirms that the object has the more specific subtype, Gosu implicitly considers that
variable’s type to be the subtype, at least within that block of code. For details, see “Basic Type Checking” on
page 252
For() Statements
The for(...in...) statement block uses a multi-part construction.
Syntax
for ( <identifier> in <expression> [ index <identifier> ] ) { <statement> }
The scope of the <identifier> is limited to the statement block itself. The <expression> in the in clause must
evaluate to one of the following:
• Array
• Java List (or any Java collection)
• Java Iterator
• String (as a list of characters)
See also “Java-based Lists as Arrays” on page 73 for details on using lists as arrays and accessing list members
using array notation.
Note: Gosu provides backwards compatibility for the use of the foreach(...) statement. However, it is
best to use the for(...) statement instead.
Automatic Iteration
Use automatic iteration to iterate automatically through the array or list members. Iteration starts with the initial
member and continues sequentially until terminating at the last member. Specify this type of iteration by using
the following syntax:
for ( member in OBJ )
In this case, OBJ must be a list, an array, an interval, or an integer. If it is an integer, Gosu iterates through the list
that many times, and the index variable if defined contains the current zero-based index value.
Examples:
for( property in Claim.TypeInfo.Properties )
for( iteration in 0..|100 )
for( iteration in 100 )
Example:
//This example prints the index of the highest score in an array of test scores.
//This particular example prints "3".
var testScores = new Number[] {91, 75, 97, 100, 89, 99}
print( getIndexOfHighestScore( testScores ) )
return highIndex
//Result
3
Example
//This example iterates over the color values in a map
var mapColorsByName = new java.util.HashMap()
//Result
red
green
blue
Examples
The following examples illustrate the different methods for iterating through the members of an array or list in a
for() block.
// Example 1: Prints all the letters with the index.
for( var letter in gw.api.util.StringUtil.splitWhitespace( "a b c d e" ) index i ) {
print( "Letter " + i + ": " + letter )
}
// Example 2: Print a message for the first exposure with 'other coverage'.
for( var exp in Claim.Exposures ) {
if( exp.OtherCoverage ) { // OtherCoverage is a Boolean property.
print( "Found an exposure with other coverage." )
// Transfer control to statement following this for…in statement
break
}
}
While() Statements
Gosu evaluates the while() expression, and uses the Boolean result (it must evaluate to true or false) to deter-
mine the next course of action:
• If the expression is initially true, Gosu executes the statements in the statement block repeatedly until the
expression becomes false. At this point, Gosu exits the while statement and continues statement execution
at the next statement after the while() statement.
• If the expression is initially false, Gosu never executes any of the statements in the statement block, and
continues statement execution at the next statement after the while() statement.
Syntax
while( <expression> ) {
<statements>
}
Example
// Print the digits
var i = 0
while( i < 10 ) {
print( i )
i = i + 1
}
Do…While() Statements
The do...while() block is similar to the while() block in that it evaluates an expression and uses the Boolean
result to determine the next course of action. The principal difference, however, is the Gosu tests the expression
for validity after executing the statement block, instead of prior to executing the statement block. This means
that the statements in the statement block executes at least once (initially).
• If the expression is initially true, Gosu executes the statements in the statement block repeatedly until the
expression becomes false. At this point, Gosu exits the do...while() block and continues statement execu-
tion at the next statement after the do...while() statement.
• If the expression is initially false, Gosu executes the statements in the statement block once, then evaluates
the condition. If nothing in the statement block has changed so that the expression still evaluates to false,
Gosu continues statement execution at the next statement after the do...while() block. If action in the state-
ment block causes the expression to evaluate to true, Gosu executes the statement block repeatedly until the
expression becomes false, as in the previous case.
Syntax
do {
<statements>
} while( <expression> )
Example
// Print the digits
var i = 0
do {
print( i )
i = i + 1
} while( i < 10 )
Switch() Statements
Gosu evaluates the switch() expression, and uses the result to choose one course of action from a set of multiple
choices. Gosu evaluate the expression, then iterates through the case expressions in order until it finds a match.
• If a case value equals the expression, Gosu execute its accompanying statement list. Statement execution
continues until Gosu encounters a break statement, or the switch statement ends. Gosu continues to the next
case (Gosu executes multiple case sections) if you omit the break statement.
• If no case value equals the expression, Gosu skips to the default case, if one exists. The default case is a case
section with the label default: rather than case VALUE:. The default case must be the last case in the list of
sections.
The switch() statement block uses a multi-part construction. The default statement is optional. However, in most
cases, it is best to implement a default case to handle any unexpected conditions.
Syntax
switch( <expression> ) {
case label1 :
[statementlist1]
[break]
[ ...
[ case labelN :
[statementlistN]
[break] ] ]
[ default :
[statementlistDefault]]
}
Example
switch( strDigitName ) {
case "one":
strOrdinalName = "first"
break
case "two":
strOrdinalName = "second"
break
case "three":
strOrdinalName = "third"
break
case "five":
strOrdinalName = "fifth"
break
case "eight":
strOrdinalName = "eighth"
break
case "nine":
strOrdinalName = "ninth"
break
default:
strOrdinalName = strDigitName + "th"
}
To improve the readability of your Gosu code, Gosu automatically downcasts the object after a typeis expres-
sion if the type is a subtype of the original type. This is particularly valuable for if statements and similar Gosu
structures such as switch. Within the Gosu code bounded by the if or switch statement, you do not need to do
casting (as TYPE expressions) to that subtype for that case. Because Gosu confirms that the object has the more
specific subtype, Gosu implicitly considers that variable’s type to be the subtype for that block of code. There
are several special cases that turn off the downcasting. For details, see “Basic Type Checking” on page 252.
Gosu Functions
Functions encapsulate a series of Gosu statements to perform an action and optionally return a value. Generally
speaking, functions exist attached to a type. For example, declaring functions within a class. As in other object-
oriented languages, functions declared on a type are also called methods.
In the context of a Gosu program (a .gsp file), you can declare functions at the top level, without attaching them
explicitly to a class. You can then call this function from other places in that Gosu program.
Note: The built-in print function is special because it is always in scope, and is not attached to a type. It is
the only true global function in Gosu.
Gosu does not support functions defined within other functions. However, you can use the Gosu feature called
blocks to do something similar. See “What Are Blocks?” on page 165 for more information.
Unlike Java, Gosu does not support variable argument functions (so-called vararg functions), meaning that Gosu
does not support arguments with “...” arguments.
Gosu permits you to specify only type literals for a function’s return type. Gosu does not support other expres-
sions that might evaluate (indirectly) to a type.
Gosu requires that you provide the return type in the function definition, unless the return type is void (no return
value). If the return type void, omit the type and the colon before it. Also, any return statement must return a
type that matches the declared function return type. A missing return type or a mismatched return value generates
a compiler error.
Syntax
[modifiers] function IDENTIFIER ( argument-declaration-list ) [:type-literal] {
function-body
}
Examples
function square( n : Number ) : Number {
return n * n
}
IMPORTANT For more information about modifiers that can appear before the word function in class
definitions, see “Modifiers” on page 135.
If the return type is not void, all possible code paths must return a value in a method that declares a return type.
In other words, if any code path contains a return statement, Gosu requires a return statement for all possible
paths through the function. The set of all paths includes all outcomes of conditional execution, such as if and
switch statements.
Gosu generates a “Missing Return Statement” error for this function and you must fix this error. The Gosu
compiler sees two separate if expressions for a total of four total code paths. Even if you believe the function is
always used with myParameter set to value 1 or 2 but no other value, you must fix the error. To fix the error,
rewrite the code so that all code paths contain a return statement.
For example, you can fix the earlier example using an else clause:
class MyClass {
function myfunction(myParameter) : boolean {
if myParameter==1
return true
else
return false
}
}
Instead of passing simply a series of one or more comma-separated arguments, pass a colon, then the argument
name, then the equals sign, then the value.
For example:
someMethod(:redisplay=true, :sendUpdate=false) // easy to read code!
Additionally, this feature lets you provide default argument values in function declarations. The function caller
can omit that argument. If the function caller passes the argument, the passed-in value overrides any declared
default value. To declare a default, follow the argument name with an equals sign and then the value.
To demonstrate default arguments, imagine a function that printed strings with a prefix:
class MyClass {
var _names : java.util.ArrayList<String>
Notice that in the printWithPrefix declaration, the prefix value has the default value " ---> ". To use the
default values, call this class with the optional arguments omitted.
The following example shows calling the printWithPrefix method using the default and also a separate time
overriding the default.
var c = new MyClass({"hello", "there"})
// Alternatively, specify the parameter to pass and override any default if one exists
c.printWithPrefix(:prefix= " next string is:")
The Gosu named arguments feature requires that the method name is not already overloaded on the class.
Calling Conventions
When you call a function with a multiple arguments, you can name some of the arguments and not others. Any
non-named arguments that you call must match in left-to-right order any arguments without defaults.
Gosu considers any additional passed-in non-named arguments as representing the arguments with defaults,
passed in the same order (left-to-right) as they are declared in the function.
Because funcA() is defined as public, it can be called from any other Gosu expression. However, funcB() is
private, and therefore is not valid anywhere except within the library.
For example, a function in another library could call funcA(), but it could not call the private funcB(). Because
funcA() is defined in the same library as funcB(), however, funcA() can call funcB().
Do not make any function public without good reason. Therefore, mark a function as private if it is defined only
for use inside the library.
IMPORTANT See “Modifiers” on page 135 for more information on class and function level access
modifiers.
Intervals
An interval is a sequence of values of the same type between a given pair of endpoint values. Gosu provides
native support for intervals. For instance, the set of integers beginning with 0 and ending with 5 is an integer
interval containing the values 0, 1, 2, 3, 4, 5. The Gosu syntax for this is 0..5. Intervals are particularly useful for
concise easy-to-understand for loops. Intervals could be a variety of types including numbers, dates, dimen-
sions, and names. You can add custom interval types. In other programming languages, intervals are sometimes
called ranges.
i++
}
Intervals do not need to be numbers. Intervals can be a variety of types including numbers, dates, dimensions,
and names. Gosu includes built-in shorthand syntax with a double period for intervals for dates and common
number types, such as the 0..10 example previously mentioned. The built-in shortcut works with the types
Integer, Long, BigInteger, BigDecimal, and Date. All decimal types map to the BigDecimal interval.
You can also add custom interval types that support any type that supports iterable comparable sequences, and
then you can use your new intervals in for loop declarations. For more information, see “Writing Your Own
Interval Type” on page 113.
If you need to get a reference to the interval’s iterator object (java.lang.Iterator), call the iterate method
and it returns the iterator.
If you have a reference to a reversed interval, you can force the interval to operate in its natural order. In other
words, you can undo the flag that marks it as reversed. Use the following syntax:
var interv = 5..0
var leftIterator = interv.iterateFromLeft()
The result is that the leftIterator variable contains the interval for 0, 1, 2, 3, 4, 5.
The iterate method, which returns the iterator, always iterates across the items in the declared order (either
regular order or reverse, depending on how you defined it).
Notice the WEEKS value. It is an enumeration constant and you do not need to qualify it with the enumeration type.
Gosu can infer the enumeration type so the code is always type-safe.
enum Color {
Red, Orange, Yellow, Green, Blue, Indigo, Violet
}
Note: For more information about creating enumerations, see “Enumerations” on page 145.
All Gosu enumerations automatically implement the java.lang.Comparable interface, which is a requirement
for intervals. However, Gosu enumerations do not automatically implement the ISequenceable interface.
To determine an iterable interval dynamically, Gosu requires that a comparable endpoint also be sequenceable.
To be sequenceable means that the class knows how to find the next and previous items in the sequence.
Sequenceable and interval types have a lot in common. They both have the concept of granularity in terms of step
amount and optionally a unit (such as weeks, months, and so on).
The interface for ISequenceable is as follows. Implement these methods and declare your class to implement this
interface.
public interface ISequenceable<E extends ISequenceable<E, S, U>, S, U> {
E nextInSequence( S step, U unit );
E nextNthInSequence( S step, U unit, int iIndex );
E previousInSequence( S step, U unit );
E previousNthInSequence( S step, U unit, int iIndex );
}
The syntax for the interface might look unusual because of the use of Gosu generics. What it really means is that
it is parameterized across three dimensions:
• The type of each (sequenceable) element in the interval.
• The type of the step amount. For example, to skip every other item, the step is 2, which is an Integer. For
typical use cases, pass Integer as the type of the step amount.
• The type of units for the interval. For example, for an integer (1, 2, 3), choose Integer. For a date interval,
the type is DateUnit. That type contains values representing days, weeks, or months. For instance,
DateUnit.DAYS. If you do not use units with the interval, type java.lang.Void for this dimension of the
parameterization. Carefully note the capitalization of this type, because it is particularly important to
access Java types, especially when using Gosu generics. In Gosu, as in Java, java.lang.Void is the spe-
cial type of the value null.
The example later in this topic has a class that extends the type:
IterableInterval<Color, Integer, void, ColorInterval>
For more information about Gosu generics, see “Gosu Generics” on page 173.
Notice that the interface can fetch both next and previous elements. It is bidirectional. Gosu needs this capability
to handle navigation from either endpoint in an interval (the reverse mode). Gosu also requires the class know
how to jump to an element by its index in the series. While this can be achieved with the single step methods,
some sequenceable objects can optimize this method without having to visit all elements in between. For
example, if the step value is 100, Gosu does not need to call the nextInSequence method 100 times to get the
next value.
The following example defines an enumeration class with additional methods that implement the required
methods of ISequenceable.
package example.pl.gs.int
uses java.lang.Integer
enum ColorSequencable
implements gw.lang.reflect.interval.ISequenceable<ColorSequencable, Integer, java.lang.Void> {
// enumeration values....
Red, Orange, Yellow, Green, Blue, Indigo, Violet
}
}
To actually use this class, run the following code in Gosu Tester:
print("Red to Blue as a closed interval...")
var colorRange = new gw.lang.reflect.interval.SequenceableInterval(
ColorSequencable.Red, ColorSequencable.Blue, 1, null, true, true, false )
for (i in colorRange) {
print(i)
}
for (i in colorRangeOpen) {
print(i)
}
This prints:
Red to Blue as a closed interval...
Red
Orange
Yellow
Green
Blue
Red to Blue as an open interval...
Orange
Yellow
Green
If you wanted your code to look even more readable, you could create your own subclass of
SequenceableInterval named for the sequenceable type you plan to use. For example,
ColorSequenceInterval.
2. Create a new class that extends (is a subclass of) the IterableInterval class parameterized using Gosu
generics across four separate dimensions:
• The type of each element in the interval
• The type of the step amount. For example, to skip every other item, the step is 2.
• The type of units for the interval. For example, for an integer (1, 2, 3), choose Integer. For a date interval,
the type is DateUnit. That type contains values representing days, weeks, or months. For instance,
DateUnit.DAYS. If you do not use units with the interval, type java.lang.Void for this dimension of the
parameterization. Carefully note the capitalization of this type, because it is particularly important to
access Java types, especially when using Gosu generics. In Gosu, as in Java, java.lang.Void is the spe-
cial type of the value null.
• The type of your custom interval. This is self-referential because some of the methods return an instance
of the interval type itself.
The example later in this topic has a class that extends the type:
IterableInterval<Color, Integer, void, ColorInterval>
For more information about Gosu generics, see “Gosu Generics” on page 173.
3. Implement the interface methods for the Interval interface.
The most complex methods to implement correctly are methods that return iterators. The easiest way to
implement these methods is to define iterator classes as inner classes to your main class. For more informa-
tion about inner classes, see “Inner Classes” on page 141.
Your class must be able to return two different types of iterators, one iterating forward (normally), and one
iterating in reverse (backward). One way to do this is to implement a main iterator. Next, implement a class
that extends your main iterator class, and which operates in reverse. On the class for the reverse iterator, to
reverse the behavior you may need to override only the hasNext and next methods.
enum Color {
Red, Orange, Yellow, Green, Blue, Indigo, Violet
}
Note: For more information about creating enumerations, see “Enumerations” on page 145.
All Gosu enumerations automatically implement the java.lang.Comparable interface, which is a requirement
for intervals.
Next, create a new class that extends the following type
IterableInterval<Color, Integer, void, ColorInterval>
Next, implement the methods from the IIterableInterval interface. It is important to note that in this example
the iterator classes are inner classes of the main ColorInterval class.
package example.pl.gs.int
uses example.pl.gs.int.Color
uses gw.lang.reflect.interval.IterableInterval
uses java.lang.Integer
uses java.util.Iterator
construct() {
throw "required start at # -- use other constructor"
}
construct(startAt : int ) {
_currentIndex = startAt
}
construct(startAt : int ) {
super(startAt)
}
Note the parameterized element type using Gosu generics syntax. It enforces the property that elements in the
interval are mutually comparable.
Finally, you can use your new intervals in for loop declarations:
uses example.pl.gs.int.Color
uses example.pl.gs.int.ColorInterval
for (i in colorRange) {
print(i)
}
for (i in colorRangeOpen) {
print(i)
}
This prints:
Red to Blue as a closed interval...
Red
Orange
Yellow
Green
Blue
Red to Blue as an open interval...
Orange
Yellow
Green
Exception Handling
Gosu supports the following standard exception handling constructions from other languages such as throw
statements, try/catch/finally blocks, and special Gosu statements such using keyword.
This topic includes:
• “Try-Catch-Finally Constructions” on page 119
• “Throw Statements” on page 120
• “Checked Exceptions in Gosu” on page 121
• “Object Lifecycle Management (‘using’ Clauses)” on page 122
Try-Catch-Finally Constructions
The try...catch...finally blocks provides a way to handle some or all of the possible errors that may occur
in a given block of code during runtime. If errors occur that the script does not handle, Gosu simply provides its
normal error message, as if there was no error handling.
The try block contains code where an error can occur, while the catch block contains the code to handle any
error that does occur.
• If an error occurs in the try block, Gosu passes program control to the catch block for processing. The initial
value of the error-identifier is the value of the error that occurred in the try block.
• If an error is thrown from Java code, the value is the exception or error that was thrown. Otherwise, the value
is an exception thrown elsewhere in Gosu code.
• If no error occurs, Gosu does not execute the catch block.
• If the error cannot be handled in the catch block associated with the try block where the error occurred, use
the throw statement. The throw statement rethrows the exception to a higher-level error handler.
After all statements in the try block have been executed and any error handling has occurred in the catch block,
the finally block is unconditionally executed.
Gosu executes the code inside the finally block, even if a return statement occurs inside the try or catch
blocks, or if an error is thrown from a catch block. Thus, Gosu guarantees that the finally block executes.
Note: Gosu does not permit you to use a return, break, or continue statement in a finally block.
Syntax
try
<try statements>
[catch( exception )
<catch statements>]
[finally
<finally statements>]
Example
try {
print( "Outer TRY running..." )
try {
print( "Nested TRY running..." )
throw "an error"
}
catch( e ) {
print( "Nested CATCH caught "+e )
throw e + " rethrown"
}
finally { print( "Nested FINALLY running..." ) }
}
catch( e ) { print( "Outer CATCH caught " + e ) }
finally { print( "Outer FINALLY running" ) }
Output
Outer TRY running...
Nested TRY running...
Nested CATCH caught an error
Nested FINALLY running...
Outer CATCH caught an error rethrown
Outer FINALLY running
Throw Statements
The throw statement generates an error condition which you can handle through the use of try…catch…finally
blocks.
WARNING Do not use throw statements as part of regular (non-error) program flow. Use them only
for handling actual error conditions.
Syntax
throw <expression>
In the following examples, notice how the error message changes if the value of x changes from 0 to 1.
Example 1
try {
var x = 0
try {
if( x == 0 ) { throw "x equals zero" }
else { throw "x does not equal zero" }
} catch( e ) {
if( e == "x equals zero" ) { return( e + " handled locally." ) }
else { throw e }
}
} catch( e ) { return( e + " handled higher up." ) }
//Output
x equals zero handled locally.
Example 2
try {
var x = 1
try {
if( x == 0 ) { throw "x equals zero" }
else { throw "x does not equal zero" }
} catch( e ) {
if( e == "x equals zero" ) { return( e + " handled locally." ) }
else { throw e }
}
} catch( e ) { return( e + " handled higher up." ) }
//Output
x does not equal zero handled higher up.
Gosu natively represents checked exceptions as an object hanging off of the caught exception in its Cause prop-
erty containing an object of type Throwable. The Cause property is null if the exception has no checked excep-
tion associated with it.
The class Throwable is the superclass of all errors and exceptions in the Java language. Use the two subclasses
Error and Exception to indicate exceptional situations occurred. Your code can understand the exception by its
subclass of those classes, such as the Java IOException or NoSuchMethodException subclasses.
For example, the following Gosu code catches any specific IOException objects stored in the Cause property
within the exception:
try {
doSomethingThatMayThrowIOException()
}
Catch( e ) {
if( e.Cause typeis IOException )
{
// Handle the IOException, which is the only type this catches
}
else
{
// rethrow the exception if it is not the right type
throw e
}
}
However, Gosu provides a concise syntax that lets you catch only specific checked exceptions in an approach
similar to Java’s try/catch syntax. Simply declare the exception of the type of exception you wish to catch:
catch( e : ThrowableSubclassName )
For example:
try {
doSomethingThatMayThrowIOException()
}
catch( e : IOException ) {
IMPORTANT The recommended Gosu coding style is not to use checked exceptions. However, if you
definitely need to handle a specific exception, use this concise syntax to make Gosu code more read-
able.
Add a finally block at the end to perform cleanup code that runs for errors and for success code paths:
try {
doSomethingThatMayThrowIOException()
}
catch( e : IOException ) {
}
finally {
// PERFORM CLEANUP HERE
}
You can simplify your code using the Gosu using statement as follows:
using( var os = SetupMyOutputStream() ) {
The parentheses after the using keyword can contain either a Gosu expression or a comma-delimited list of one
or more Gosu statements. Gosu runs any statements (including variable assignment) at run time and uses the
result as an object to manage in the using clause.
Note: You do not need an additional return statement to pass the value to the using clause. Also note that
the statements must be delimited with commas, not semicolons.
There are several categories of objects that work with the using keyword: disposable objects, closeable objects,
and reentrant objects. If you try to use an object that does not satisfy the requirements of one of these categories,
Gosu displays a compile error. The following subtopics discuss these three types of objects.
Note: If Gosu detects that an object is more than one category, at run time Gosu considers the object only
one category, defined by the following precedence: disposable, closeable, reentrant. For example, if an
object has a dispose and close method, Gosu only calls the dispose method.
You can return values from uses clauses using the standard return statement, discussed further in “Returning
Values from ‘using’ Clauses” on page 126.
Disposable Objects
Disposable objects are objects that Gosu can dispose to release all system resources. For Gosu to recognize a
valid disposable object, the object must have one of the following attributes:
• The object implements the Gosu interface IDisposable. This interface contains only a single method called
dispose. This method takes no arguments. Always use a type that implements IDisposable if possible due to
faster run time performance.
• The object has a dispose method even if it does not implement the IDisposable interface. This approach
works but is slower at run time because Gosu must use reflection (examining the type at run time) to find the
method.
A type’s dispose method must release all the resources that it owns. The dispose method must release all
resources owned by its base types by calling its parent type’s dispose method.
To help ensure that resources clean up appropriately even under error conditions, you must design your dispose
method such that Gosu can call it multiple times without throwing an exception. In other words, if the stream is
already closed, then invoking this method has no effect nor throw an exception.
}
}
In contrast, you can write more readable Gosu code using the using keyword:
using( var writer = new FileWriter( "c:\\temp\\test1.txt" ) )
{
writer.write( "I am text within a file." )
}
...
function useReentrantLockOld() {
_lock.lock()
try {
// do your main work here
}
finally {
_lock.unlock()
}
}
In contrast, you can write more readable Gosu code using the using keyword:
// in your class variable definitions...
var _lock : ReentrantLock = new ReentrantLock()
function useReentrantLockNew() {
using( _lock ) {
// do your main work here
}
}
Similarly, you can cast any object to a monitor lock by adding “as IMonitorLock” after the object. For example,
the following method call code uses itself (using the special keyword this) as the monitor lock:
function monitorLock() {
using( this as IMonitorLock ) {
// do stuff
}
}
For example:
using( var out = new FileOutputStream( this, false ) ) {
out.write( content )
}
You can combine the multiple item feature with the ability to assign variables. For more about assigning vari-
ables, see “Assigning Variables Inside ‘using’ Expression Declaration” on page 125 .
For example:
using( var lfc = new FileInputStream(this).Channel,
var rfc = new FileInputStream(that).Channel ) {
lbuff.clear()
rbuff.clear()
}
return false
}
}
Gosu ensures that all objects are properly cleaned up. In other words, for each object to create or resource to
acquire, if it creates or acquires successfully, Gosu releases, closes, or disposes the object. Also note that if one of
the resources fails to create, Gosu does not attempt to acquire other resources in later-appearing items in the
command-seperated list. Instead, Gosu simply releases the ones that did succeed.
IMPORTANT There is much more information about concurrency in the section “Concurrency” on
page 269, including other concurrency APIs.
Classes
Gosu classes encapsulate data and code for a specific purpose. You can subclass and extend existing classes. You
can store and access data and functions (also called methods if part of a class) on an instance of the class or on
the class itself.
Gosu classes are the foundation for syntax of syntax for interfaces, enumerations, and enhancements. Some of
the information in this topic applies to those features as well. For example, the syntax of variables, methods, and
modifiers are the same in interfaces, enumerations, and enhancements.
Related topics:
• “Interfaces” on page 147
• “Enumerations” on page 145
• “Enhancements” on page 161
This topic includes:
• “What Are Classes?” on page 127
• “Creating and Instantiating Classes” on page 128
• “Properties” on page 130
• “Modifiers” on page 135
• “Inner Classes” on page 141
You can also extend an existing class, which means to make a subclass of the class with new methods or proper-
ties or different behaviors than existing implementations in the superclass.
Gosu classes are analogous to Java classes in that they have a package structure that defines the namespace of
that class within a larger set of names. For example, if your company is called Smith Company and you were
writing utility classes to manipulate addresses, you might create a new class called NotifyUtils in the name-
space smithco.utilities. The fully-qualified name of the class would be smithco.utilities.NotifyUtils.
You can write your own custom classes and call these classes from within Gosu, or call built-in classes. You
create and reference Gosu classes by name just as you would in Java. For example, suppose you define a class
called Notification in package smithco.utilities with a method (function) called getName().
You can create an instance of the class and then call a method like this:
// create an instance of the class
var myInstance = new smithco.utilities.Notification()
If desired, you can also define data and methods that belong to the class itself, rather than an instance of the class.
This is useful for instance to define a library of functions of similar purpose. The class encapsulates the functions
but you never need to create an instance of the class. You can create static methods on a class independent of
whether any code ever creates an instance of the class. You are not forced to choose between the two design
styles. For more information, see “Static Modifier” on page 140.
If desired, you can write Gosu classes that extend from Java classes. Your class can include Gosu generics
features that reference or extend Java classes or subtypes of Java classes. See “Gosu Generics” on page 173 for
more information about generics.
Define methods with the keyword function followed by the method name and the argument list in parentheses,
or an empty argument list if there are no arguments to the method. The parameter list is a list of arguments, sepa-
rated by commas, and of the format:
parameterName : typeName
A simple Gosu class with one instance variable and one public method looks like the following:
class MyClass
{
var myStringInstanceVariable : String
}
}
Constructors
A Gosu class can have a constructor, which is like a special method within the class that Gosu calls after creating
an instance of that type. For example, if Gosu uses code like “new MyClass()”, Gosu calls the MyClass class’s
constructor for initialization or other actions. To create a constructor, name the method simply construct. For
example:
class Tree
{
construct()
{
print("A Tree object was just created!")
}
}
If desired, you can delete the class constructor if you do not need it.
Your class might extend another class. If so, it is typically appropriate for your constructor to call its superclass
constructor. To do this, use the super keyword. It must be the first line in the subclass constructor. For example
class Tree extends Plant
{
construct()
{
super()
print("A Tree object was just created!")
}
}
If you call super(), Gosu calls the superclass no-argument constructor. If you call super(parameter_list), Gosu
calls the superclass constructor that matches the matching parameter list. Note that you can call a superclass
constructor with different number of arguments or different types than the current constructor.
Do not do this:
public var FirstName : String // do not do this. Public variables are not standard Gosu style
For more information about defining properties, see “Properties” on page 130.
IMPORTANT The standard Gosu style is to use public properties backed by private variables instead
of using public variables. Do not use public variables in new Gosu classes. See “Properties” on
page 130 for more information.
You can also use object initializers allow you to set properties on an object immediately after a new expression.
Use object initializers for compact and clear object declarations. They are especially useful if combined with data
structure syntax and nested objects. A simple version looks like the following:
var sampleClaim = new Claim(){ :ClaimId = "TestID" }
For more information on new expressions and object initializers, see “New Object Expressions” on page 86.
Note: You can use Gosu classes without creating a new instance of the class using static methods, static
variables, and static properties. For more information, see “Static Modifier” on page 140.
Properties
Gosu classes can define properties, which appear to other objects like variables on the class in that they can use
simple intuitive syntax with the period symbol (.) to access a property for setting or getting the property.
However, you can implement get and set functionality with Gosu code. Although code that gets or sets properties
might simply get or set an instance variable, you can implement properties in other more dynamic ways.
To get and set properties from an object with Field1 and Field2 properties, just use the period symbol like
getting and setting standard variables:
// create a new class instance
var a = new MyClass()
// set a property
a.Field1 = 5
// get a property
print (a.Field2)
In its most straightforward form, a class defines properties like functions except with the keywords
“property get” or “property set” before it instead of “function”. The get property function must take zero
parameters and the set property function always takes exactly one parameter.
For example, the following code defines a property that supports both set and get functionality:
class MyClass {
property get Field3() : String {
return "myFirstClass" // in this simple example, do not really return a saved value
}
property set Field3(str : String) {
print (str) // print only ---- in this simple example, do not save the value
The set property function does not save the value in that simple example. In a more typical case, you probably
want to create a class instance variable to store the value in a private variable:
class MyClass {
private var _field4 : String
Although the data is stored in private variable _field4, code that accesses this data does not access the private
instance variable directly. Any code that wants to use it simply uses the period symbol (.) with the property
name:
var f = new MyClass()
f.Field4 = "Yes" // sets to "Yes" by calling the set property function
var g = f.Field4 // calls the get property function
For some classes, your property getter and setter methods may do very complex calculations or store the data in
some other way than as a class variable. However, it is also common to simply get or set a property with data
stored as a common instance variable. Gosu provides a shortcut to implement properties as instance variables
using variable alias syntax using the as keyword followed by the property name to access the property. Use this
approach to make simple automatic getter and setter property methods backed by an class instance variable.
For example, the following code is functionally identical to the previous example but is much more concise:
class MyClass {
private var _field4 : String as Field4
}
The standard Gosu style is to use public properties backed by private variables instead of using public variables.
In other words, write your Gosu classes to look like:
private var _firstName : String as FirstName
This declares a private variable called _firstname, which Gosu exposes as a public property called FirstName.
Do not write your classes to look like:
public var FirstName : String
IMPORTANT The standard Gosu style is to use public properties backed by private variables instead
of using public variables. Do not use public variables in new Gosu classes.
Code defined in that class does not need to access the property name. Classes can access their own private vari-
ables. In the previous example, other methods in that class could reference _field4 or _firstname variables
rather than relying on the property accessors Field4 or FirstName.
Properties Act Like Data But They Are Dynamic and Virtual Functions
In contrast to standard instance variables, get property and set property functions are virtual, which means
you can override them in subclasses and implement them from interfaces. The following illustrates how you
would override a property in a subclass and you can even call the superclass’s get or set property function:
class MyClass
{
var _easy : String as Easy
}
The overridden property get function first calls the implicitly defined get function from the superclass, which
gets class variable called _easy, then appends a string. This get function does not change the value of the class
variable _easy, but code that accesses the Easy property from the subclass gets a different value.
For example, if you write the following code in the Gosu Tester:
var f = new MyClass()
var b = new MySubClass()
f.Easy = "MyPropValue"
b.Easy = "MyPropValue"
print(f.Easy)
print(b.Easy)
If any object to the left of the period character is null, the null-safe period operator does not throw a null pointer
exception (NPE) and the expression returns null. Gosu null-safe property paths tends to simplify real-world
code. Often, a null expression result has the same meaning whether the final property access is null or whether
earlier parts of the path are null. For such cases in Gosu, do not bother to check for null value at every level of
the path. This makes your Gosu code easier to read and understand.
For example, suppose you had a variable called house, which contained a property called Walls, and that object
had a property called Windows. You could get the Windows value with the following syntax:
house.Walls.Windows
In some languages, you must worry that if house is null or house.Walls is null, your code throws a null
pointer exception. This causes programmers to use the following common coding pattern:
// initialize to null
// check earlier parts of the path for null to avoid a null pointer exceptions (NPEs)
if( house != null and house.Walls != null ) {
x = house.Walls.Windows
}
The following concise Gosu code is equivalent to the previous example and avoids any null pointer exceptions:
var x = house?.Walls?.Windows
If house is null, Gosu throws an NPE exception. Gosu assumes that method calls might have side effects, so
Gosu cannot quietly skip the method call and return null.
In contrast, a null-safe method call does not throw an exception if the left side of the period character is null.
Gosu just returns null from that expression. In contrast, using the ?. operator calls the method with null safety:
house?.myaction()
If house is null, Gosu does not throw an exception. Gosu simply returns null from the expression.
See Also
• For more examples and discussion, see “Handling Null Values In Expressions” on page 95
IMPORTANT Expose public data as properties rather than as getter functions. This allows you to take
advantage of Gosu null-safe property accessor paths. Additionally, note it is standard Gosu practice to
separate your implementation from your class’s interaction with other code by using properties rather
than public instance variables. Gosu provides a simple shortcut with the as keyword to expose an
instance variable as a property. See “Properties” on page 130
Because null coerces implicitly to Boolean (the type of the Empty property), the expression evaluates to false in
either of the following cases:
• if obj.StringProperty is null
• the String is non-null but its Empty property evaluates to false.
In typical code, it is important to distinguish these two very different conditions cases. For example, if you
wanted to use the value obj.StringProperty only if the value is non-empty, it is insufficient to just check the
value obj.StringProperty.Empty.
To work around this, Gosu adds an enhancement property to java.util.String called HasContent. This effec-
tively is the reverse of the logic of the Empty property. The HasContent property only returns true if it has
content. As a result, you can use property accessor paths such as the following:
if (obj.StringProperty.HasContent)
Because null coerces implicitly to Boolean (the type of the Empty property), the expression evaluates to false in
either of the following cases:
• if obj.StringProperty is null
• the String is non-null but the string has no content (its HasContent property evaluates to false).
These cases are much more similar semantically than for the variant that uses Empty
(obj.StringProperty.Empty). This means you are more likely to rely on path expressions like this.
Be sure to consider null-safety of property paths as you design your code, particularly with Boolean properties.
Static Properties
You can use properties directly on the class without creating a new instance of the class. For more information,
see “Static Modifier” on page 140.
class MyFirstClass {
// Explicit property setter for _f2, visible only to classes in this package
internal property set F2( value : String ) {
_f2 = value
}
Assign a property value. This internally calls a hidden method to assign "hello" to variable _f0:
test.F0 = "hello"
Get a property value. This indirectly calls the mySecondClass property getter function for F2:
print( test.F2 ) // prints null because it is not set yet
The following line is invalid because F2 is not visible outside of the package namespace of MySecondClass. F2 is
publicly read-only.
// This gives a compile error.
test.F2 = "hello"
The following line is invalid since Calculation is read-only (it does not have a setter function):
//This gives a compiler error.
test.Calculation = 123
Demonstrate that properties can be overridden through inheritance because properties are virtual:
print( test.Fred ) // prints "myFirstClass suffix"
Modifiers
There are several types of modifiers:
• Access Modifiers
• Override Modifier
• Abstract Modifier
• Final Modifier
• Static Modifier
Access Modifiers
You can use access modifier keywords to set the level of access to a Gosu class, interface, enumeration, or a type
member (a function, variable, or property). The access level determines whether other classes can use a particular
variable or invoke a particular function.
For example, methods and variables marked public are visible from other classes in the package. Additionally,
because they are public, functions and variables also are visible to all subclasses of the class and to all classes
outside the current package. For example, the following code uses the public access modifier on a class vari-
able:
package com.mycompany.utils
class Test1 {
public var Name : String
}
In contrast, the internal access modifier lets the variable be accessed only in the same package as the class:
package com.mycompany.utils
class Test2 {
internal var Name : String
}
For example, another class with fully qualified name com.mycompany.utils.Test2 could access the Name vari-
able because it is in the same package. Another class com.mycompany.integration.Test3 cannot see the
Test.Name variable because it is not in the same package.
Some modifiers only apply to type members (functions, variables, properties, and inner types) and some modi-
fiers apply to type members and top-level types (outer Gosu classes, interfaces, enumerations).
The following table lists the Gosu access modifiers and each one’s applicability and visibility:
If you do not specify a modifier, Gosu assumes the following default access levels:
Variables private
Functions public
Properties public
Override Modifier
Apply the override modifier to a function or property implementation to declare that the subtype overrides the
implementation of an inherited function or property with the same signature.
For example, the following line might appear in a subtype overriding a myFunction method in its superclass:
override function myFunction(myParameter : String )
If Gosu detects that you are overriding an inherited function or method with the same name but you omit the
override keyword, you get a compiler warning. Additionally, the Gosu editor offers to automatically insert the
modifier if it seems appropriate.
Abstract Modifier
The abstract modifier indicates that a type is intended only to be a base type of other types. Typically an
abstract type does not provide implementations (actual code to perform the function) for some or all of its func-
tions and properties. This modifier applies to classes, interfaces, functions, and properties.
For example, the following is a simple abstract class:
abstract class Vehicle {
}
If a type is specified as abstract, Gosu code cannot construct an instance of it. For example, you cannot use code
such as new MyType() with an abstract type. However, you can instantiate a subtype of the type if the subtype
fully implements all abstract members (functions and properties). A subtype that contains implementations for
all abstract members of its supertype is referred to as a concrete type.
For example, if class A is abstract and defines one method’s parameters and return value but does not provide
code for it, that method would be declared abstract. Another class B could extend A and implement that method
with real code. The class A is the abstract class and the class B is a concrete subclass of A.
An abstract type may contain implementations for none of its members if desired. This means that you cannot
construct an instance of it, although you can define a subtype of it and instantiate that type. For example, suppose
you write an abstract Gosu class called Vehicle which might contain members but no abstract members, it might
look like this:
package com.mycompany
You could not construct an instance of this class, but you could define another class that extends it:
package com.mycompany
You can now use code such as the following to create an instance of Truck:
var t = new Truck()
Things work differently if the supertype (in this case, Vehicle) defines abstract members. If the supertype
defines abstract methods or abstract properties, the subtype must define an concrete implementation of each
abstract method or property to instantiate of the subclass. A concrete method implementation must implement
actual behavior, not just inherit the method signature. A concrete property implementation must implement
actual behavior of getting and setting the property, not just inherit the property’s name.
The subtype must implement an abstract function or abstract property with the same name as a supertype. Use
the override keyword to tell Gosu that the subtype overrides an inherited function or method with the same
name. If you omit the override keyword, Gosu displays a compiler warning. Additionally, the Gosu editor offers
to automatically insert the override modifier if it seems appropriate.
For example, suppose you expand the Vehicle class with abstract members:
package com.mycompany
/* create a class instance variable that uses the "as ..." syntax to define a property
* By doing this, you make a concrete implementation of the abstract property "Plate"
*/
var _licenseplate : String as Plate
You can now construct an instance of the concrete subtype Truck, even though you cannot directly construct an
instance of the supertype Vehicle because it is abstract.
You can test these classes using the following code in the Gosu Tester:
var t = new com.mycompany.Truck()
t.Plate = "ABCDEFG"
print("License plate = " + t.Plate)
t.RegisterWithDMV( "http://dmv.ca.gov/register" )
Final Modifier
The final modifier applies to types, type members, local variables, and function parameters. It specifies that the
value of a property, local variable, or parameter cannot be modified after the initial value is assigned. The final
modifier cannot be combined with the abstract modifier on anything. These modifiers are mutually exclusive.
The final modifier implies that there is a concrete implementation and the abstract modifier implies that there
is no concrete implementation.
Final Types
If you use the final modifier on a type, the type cannot be inherited. For example, if a Gosu class is final, you
cannot create any subclass of the final class.
The final modifier is implicit with enumerations, which are an encapsulated list of enumerated constants, and
they are implemented like Gosu classes in most ways. For more information, see “Enumerations” on page 145.
This means that no Gosu code can subclass an enumeration.
class Auto {
In many ways, properties are implemented like functions in that they are defined with code and they are virtual.
Being virtual means properties can be overridden and can call an inherited get or set property function in their
supertype. For more information about properties and shortcuts to define properties backed by instance variables,
see “Properties” on page 130.
If you define a variable as final, you must initialize it with a value immediately as you declare the variable. You
cannot declare the variable as final and initialize it in a later statement.
class FinalTest
{
function SuffixTest( greeting : String) {
greeting = greeting + "fly"
print(greeting)
}
}
This prints:
Butterfly
However, if you add the final modifier to the parameter, the code generates a compile error because the function
attempts to modify the value of a final parameter:
class final1
{
function SuffixTest( final greeting : String) {
greeting = greeting + "fly"
print(greeting)
}
}
Static Modifier
Static Variables
Gosu classes can define a variable stored once per Gosu class, rather than once per instance of the class. This can
be used with variables and properties. If a class variable is static, it is referred to as a static variable.
WARNING If you use static variables in a multi-threaded environment, you must take special precau-
tions to prevent simultaneous access from different threads. Use static variables sparingly if ever. If
you use static variables, be sure you understand synchronized thread access fully. For more informa-
tion, see “Concurrency” on page 269.
To use a Gosu class variable, remember to set its access level such as internal or public so it is accessible to
class that need to use it. For more information access levels, see “Access Modifiers” on page 136.
The static modifier cannot be combined with the abstract modifier. See “Abstract Modifier” on page 137 for
more information.
The Name property get and set functions and the PrintGreeting method are part of the Greeting class itself
because they are marked as static.
Consequently, this code in the Gosu Tester accesses properties on the class itself, not an instance of the class:
Greeting.Name = "initial value"
print(Greeting.Name)
Greeting.PrintGreeting()
Notice that this example never constructs a new instance of the Greeting class using the new keyword.
class Greeting
{
static class FrenchGreeting {
static public function sayWhat() : String {
return "Bonjour"
}
}
You can test this in the Gosu Tester using the code:
print(example.Greeting.Hello)
This prints:
Boujour
For more information about this topic, refer to the next section, “Inner Classes” on page 141.
Inner Classes
You can define inner classes in Gosu, similar to inner classes in Java. They are useful for encapsulating code
even further within the same file as related code. Use named inner classes if you want to be able to refer to the
inner class from multiple related methods or multiple related classes. Use anonymous inner classes if you just
need a simple subclass that you can define in-line within a class method.
Inner classes optionally can include generics features (see “Gosu Generics” on page 173).
class Greeting
{
static class FrenchGreeting {
static public function sayWhat() : String {
return "bonjour"
}
}
You can test this in the Gosu Tester using the code:
print(example.Greeting.Hello)
This prints:
bonjour
Notice that this example never constructs a new instance of the Greeting class or the FrenchGreeting class
using the new keyword. The inner class in this example has the static modifier. For more information the static
modifier, see “Static Modifier” on page 140.
Similarly, classes that derive from the outer class can use the inner class FrenchGreeting. The following
example subclasses the Greeting class:
package example
You can test this code using the following code in the Gosu Tester:
var t = new example.OtherGreeting()
t.greetme()
This prints:
bonjour
class InnerTest {
// anonymous inner classes can have variables (public, private, and so on)
private var i = 0
counter.incrementMe()
counter.incrementMe()
counter.incrementMe()
counter.incrementMe()
counter.incrementMe()
}
}
You can use the following code in the Gosu Tester to test this class:
example.InnerTest.runme()
This prints:
Value is 0 at creation!
Value is 1
Value is 2
Value is 3
Value is 4
Value is 5
class Vehicle
{
construct()
{
print("A vehicle was just constructed!")
}
You can create a different class that uses Vehicle and defines an anonymous inner class based on Vehicle:
package example
class FancyVehicle
{
Notice that the inner class that defines the actionTwo method uses the new operator and not the class operator.
What it actually does, however, is define a new class with no name and then creates one instance of it.
You can test the FancyVehicle class with the following code in Gosu Tester:
var g = new example.FancyVehicle()
g.testInner()
This prints:
A vehicle was just constructed!
actionOne was called with arg USA
actionTwo was called with arg ABCDEFG
For example, suppose the PluginCallbackHandler class contains an inner interface called
PluginCallbackHandler.Block, which implements a run method, similar to the Runnable interface. This inter-
face has one method. Instead of creating an anonymous class to use the inner interface, use a block that takes no
arguments and has no return value.
For example, suppose you are using this PluginCallbackHandler class definition in Java:
public interface PluginCallbackHandler {
// ...
However, you can write it more concisely using Gosu block syntax:
public function messageReceived(messageId : int) {
For more information about blocks, see “Gosu Blocks” on page 165.
Enumerations
An enumeration is a list of named constants that are encapsulated into a special type of class. Gosu supports
enumerations natively, as well as provides compatibility to use enumerations defined in Java.
This topic includes:
• “Using Enumerations” on page 145
Using Enumerations
An enumeration is a list of named constants that are encapsulated into a special type of class. For example, an
application tracking cars might want to store the car manufacturer in a property, but track them as named
constants that can be checked at compile-time. Gosu supports enumerations natively and also is compatible with
enumerations defined in Java.
To create an enumeration
1. Create a class by that name using the same approach you use to create a class.
package example
class FruitType {
construct() {
}
}
2. Change the keyword class to enum and remove the constructor. Your enumeration now looks like:
package example
enum FruitType {
To extract the name of the enumeration value as a String, get its Name property. To extract the index of the
enumeration value as an Integer, get its Ordinal property.
For example:
print(myFruitType.Name) // prints "Banana"
Comparing Enumerations
You can compare two enumerations using the == operator. For example,
if (myFruitType == FruitType.Apple)
print("An apple a day keeps the doctor away.")
if (myFruitType == FruitType.Banana)
print("Watch out for banana peels.")
Interfaces
Gosu can define and implement interfaces that define a strict contract of interaction and expectation between two
or more software elements. From a syntax perspective, interfaces look like class definitions but merely specify a
set of required functions necessary for any class that implements the interface. An interface is conceptually a list
of method signatures grouped together. Some other piece of code must implement that set of methods to success-
fully implement that interface. Gosu classes can implement interfaces defined in either Gosu or Java.
This topic includes:
• “What is an Interface?” on page 147
• “Defining and Using an Interface” on page 148
What is an Interface?
Interfaces are a set of required functions necessary for a specific task. Interfaces define a strict contract of inter-
action and expectation between two or more software elements, while leaving the implementation details to the
code that implements the interface. In many cases, the person who writes the interface is different from the
person who writes code to implement the interface.
To take a real-world example of an interface, imagine a car stereo system. The buttons, such as for channel up
and channel down, are the interface between you and the complex electrical circuits on the inside of the box. You
press buttons to change the channel. However, you probably do not care about the implementation details of how
the stereo performs those tasks behind the solid walls of the stereo. If you get a new stereo, it has equivalent
buttons and matching behavior. Since you interact only with the buttons and the output audio, if the user interface
is appropriate and outputs appropriate sounds, the internal details do not matter to you. You do not care about the
details of how the stereo internally handles the button presses for channel up, channel down, and volume up.
If a Gosu class implements this interface, Gosu validates at compile time that all required methods are present
and that the implementor class has the required method signatures.
An interface appears like a group of related method signatures with empty bodies grouped together for the
purpose of some other piece of code implementing the methods. if a class implements the interface, the class
agrees to implement all these methods with the appropriate method signatures. The code implementing the inter-
face agrees that each method appropriately performs the desired task if external code calls those methods.
You can write Gosu classes that implement or extend interfaces defined in Gosu or defined in Java.
To implement an interface, create a different Gosu class and add “implements MyInterfaceName” after the class
name. For example, if your class is called MyRestaurant, go to the line:
class MyRestaurant
If a class implements more than one interface, separate the interface names by commas:
class MyRestaurant implements Restaurant, InitializablePlugin
In the example Restaurant interface, you can implement the interface with a class such as:
class MyRestaurant implements Restaurant
The Gosu editor reveals compilation errors if your class does not properly implement the plugin interface. You
must fix these issues.
A common compilation issue is that a method that interface methods that look like properties must be imple-
mented in Gosu explicitly as a Gosu property. In other words, if the interface contains a method whose name
starts with "get" or "is" and takes no parameters, define the method using the Gosu property syntax. In this
case, do not use the function keyword to define it as a standard class method.
For example, if interface IMyInterface declares methods isVisible() and getName(), your plugin implemen-
tation of this interface might look like:
class MyClass implements IMyInterface {
For more information about properties, see “Defining and Using Properties with Interfaces” on page 149.
If desired, you can write Gosu interfaces that extend from Java interfaces. You can also have your interface
include Gosu generics. Your class can extend from Java classes that support generics. Your class can abstract an
interface across a type defined in Java or a subtype of such a type. (For more information about generics, see
“Gosu Generics” on page 173.)
Classes can implement an interface property with the explicit property get or property set syntax.
For example, if the interface is defined as:
package example
interface MyInterface
{
property get VolumeLevel() : int
property set VolumeLevel(vol : int) : void
}
Alternatively, a class implementing a property can implement the property using the variable alias syntax using
the as keyword. This language feature lets you make simple get and set methods that use an class instance vari-
able to store the value, and to get the value if anyone requests it.
For example, the following code is functionally identical to the previous example implementation of MyStereo,
but it is much more concise:
uses example.MyStereo
class MyStereo implements MyInterface
{
var _volume : int as VolumeLevel
}
If you run the Gosu tester code as before, it prints the same results.
For information about Gosu class properties in general, see “Classes” on page 127.
Superclass Properties
When implementing an interface and referencing a superclasses’ property, use the super.PropertyName syntax,
such as:
property get Bar() : String {
... _mySpecialPrivateVar = super.Foo + super.Bar
}
Composition
Gosu supports the language feature called composition using the delegate keyword in variable definitions.
Composition allows a class to delegate responsibility for implementing an interface to a different object. This
compositional model allows easy implementation of objects that are proxies for other objects, or encapsulating
shared code independent of the type inheritance hierarchy.
This topic makes extensive references to the following topics:
• “Interfaces” on page 147
• “Classes” on page 127
This topic includes:
• “Using Gosu Composition” on page 151
Let us consider a general example to illustrate this situation. Suppose you have a window class and a clipboard-
support class. Suppose you have a user interface system with different types of objects and capabilities.
However, some of the capabilities might not correspond directly to the class inheritance. For example, suppose
you have classes for visual items like windows and buttons and scroll bars. However, only some of these items
might interact with the clipboard copy and paste commands.
If not all user interface items do not support the clipboard, you might not want to implement your clipboard-
supporting code in the root class for your user interface items. However, where do you put the clipboard-related
code if you want to write a window-handling class that is also a clipboard part? One way to do this is to define a
new interface that describes what methods each class must implement to support clipboard behavior. Each class
that uses this interface implements the interface with behavior uniquely appropriate to each class. This is an
example of sharing a behavioral contract defined by the interface. However, each implementation is different
within each class implementation.
What if the actual implementation code for the clipboard part is identical for each class that uses this shared
behavior? Ideally, you write shared code only once so you have maximum encapsulation and minimal duplica-
tion of code. In some cases there does not exist a shared root class other than Object, so it might not be an option
to put the code there. If Gosu supported multiple inheritance, you could encapsulate the shared code in its own
class and classes could inherit from that class in addition to any other supertype.
Fortunately, you can get many of the benefits of multiple inheritance using another design pattern called compo-
sition. Composition encapsulates implementation code for shared behavior such that calling a method on the
main object forwards method invocations to a subobject to handle the methods required by the interface.
Let us use our previous example with clipboard parts and windows. Let us suppose you want to create a subclass
of window but that implements the behaviors associated with a clipboard part. First, create an interface that
describes the required methods that you expect a clipboard-supporting object to support, and call it
IClipboardPart. Next, create an implementation class that implements that interface, and call it
ClipboardPart. Next, create a window subclass that implements the interface and delegates the actual work to a
ClipboardPart instance associated with your window subclass.
The delegation step requires the Gosu keyword delegate within your class variable definitions. Declaring a
delegate is like declaring a special type of class variable.
The delegate keyword has the following syntax:
delegate PRIVATE_VARIABLE_NAME represents INTERFACE_LIST
Or optionally
delegate PRIVATE_VARIABLE_NAME : TYPE represents INTERFACE_LIST
The INTERFACE_LIST is a list of one or more interface names, with commas separating multiple interfaces.
For example:
delegate _clipboardPart represents IClipboardPart
Within the class constructor, create an instance of an object that implements the interface. For example:
construct() {
_clipboardPart = new ClipboardPart( this )
}
After that point in time, Gosu intercepts any method invocations on the object for that interface and forward the
method invocation to the delegated object.
Let us look at complete code for this example.
The interface:
package test
interface IClipboardPart
{
function canCopy() : boolean
function copy() : void
function canPaste() : boolean
function paste() : void
construct(owner : Object) {
_myOwner = owner
}
construct() {
_clipboardPart = new ClipboardPart( this )
}
}
It prints:
Pasted!
For example,
private delegate _clipboardPart : ClipboardPart represents IClipboardPart
You might notice that in this example the line does not specify an explicit type for _employee and yet it repre-
sents two different types (in this case, two interface types). You might wonder about the compile-time type of the
variable called _employee. Because the variable must satisfy all requirements of both types, Gosu uses a special
type called a compound type. A literal of this type is expressed in Gosu as a list separated by the ampersand
symbol (&). For example:
ISalariedEmployee & IOfficer
Typical code does not need to mention a compound type explicitly. However, remember this syntax in case you
see it during debugging code that uses the delegate keyword with multiple interfaces.
For more details of compound types, see “Compound Types” on page 260.
For example:
class MyStringList implements List<String>
{
delegate _internalList represents List<String> = new ArrayList<String>()
}
You could now use this class and call any method defined on the List interface:
var x = new MyStringList()
x.add( "TestString" )
Annotations
Gosu annotations are a simple syntax to provide metadata about a Gosu class, constructor, method or property.
This annotation can control the behavior of the class, the documentation for the class.
This topic includes:
• “Annotating a Class, Method, Type, or Constructor” on page 155
• “Annotations at Run Time” on page 157
• “Defining Your Own Annotations” on page 158
In some cases, you follow the annotation name with an argument list within parentheses. The following example
specifies a function might throw a specific exception using arguments to the annotation:
class MyClass{
The annotation may not require any arguments, or the arguments may be optional. If so, you can omit the paren-
theses. For example, suppose you add an annotation called MyAnnotation that takes no arguments. You could use
it in the following (verbose) syntax:
@MyAnnotation()
Since there are no arguments, you can optionally omit the parentheses:
@MyAnnotation
You can use annotations defined natively in Gosu or directly use Java annotations.
For related information about named arguments, see “Named Functions Arguments and Argument Defaults” on
page 108.
Built-in Annotations
The Gosu language includes built-in annotations defined in the gw.lang.* package, which is always in scope, so
their fully-qualified name is not required.
The following table lists the built-in general annotations:
The following code defines a class that uses several built-in annotations:
package com.mycompany
uses java.lang.Exception
@WsiWebService
class Test
{
@Param("Name", "The user's name. Must not be an empty string.")
@Returns("A friendly greeting with the user's name")
@Throws(Exception, "General exception if the string passed to us is empty or null")
public function FriendlyGreeting(Name : String) : String {
}
}
The following example specifies that a method is deprecated, which means it was a valid API but not anymore.
A deprecated API is temporarily available but a future release will remove it. Immediately start to refactor code
that uses deprecated APIs. This ensures your code is compatible with future releases, which will simplify your
upgrades.
class MyClass {
Because annotations are implemented as Gosu classes (see “Defining Your Own Annotations” on page 158), the
annotation class that you are implicitly using must be in the current Gosu scope. You can ensure that it is in scope
by fully qualifying the annotation. For example, if the SomeAnnotation annotation is defined within the package
com.mycompany.some.package, specify the annotation like:
@com.mycompany.some.package.SomeAnnotation
class SomeClass {
...
}
Alternatively, import the package using the Gosu uses statement and then use the annotation more naturally and
concisely by using only its name:
uses com.mycompany.some.package.SomeAnnotation.*
@SomeAnnotation
class SomeClass {
...
}
Get annotations on a
specific instance of a... Example using the @Deprecated annotation
Using these methods, the return result is automatically statically typed as a list of the proper type. Using the
examples in the previous table, the result would be of type:
List<Deprecated>
This type is shown using generics syntax, and it means “a list of instances of the Deprecated annotation class”.
For more information about generics, see “Gosu Generics” on page 173.
You can additionally get all annotations (not just one annotation type) using the two properties Annotations and
DeclaredAnnotations. These two properties are slightly different and resemble the Java versions of annotations
with the same name. On types and interfaces, Annotations returns all annotations on this type/interface and on
all its supertypes/superinterfaces. DeclaredAnnotations returns annotations only on the given types, ignoring
supertypes/superinterfaces. In constructors, properties, and methods, the Annotations and
DeclaredAnnotations properties return the same thing: all annotations including supertypes/superinterfaces. In
the examples in the table, the variable i represents the index in the list. In practice, you would probably search
for it by name using List methods like list.firstWhere(\ s -> s.Name = "MethodName").
For a detailed example of accessing annotations at run time, see “Defining Your Own Annotations” on page 158.
In this case the annotation has no constructor, which implies the annotation takes no parameters, so it could
simply be called as:
@Author()
However, as written in this example so far, you used the annotation but not specified any authors. Annotations
can define arguments so you can pass information to the annotation, which might stored in private variables.
Annotations can have properties or arguments of any type. However, if defining properties and arguments, be
careful you never define circular references between annotation classes and regular classes.
This example requires only a single String argument, so define the annotation Author to take one argument to
its constructor. Gosu calls the constructor once for the type after initializing Gosu at run time. In your
constructor, save the constructor arguments value in a private variable:
package com.guidewire.pl.docexamples.annotations
construct(a : String)
{
// The constructor takes a String, which means the Author of this item
_author = a;
}
}
In this example, the annotation saves the String argument in a class instance variable called _author. Because of
the phrase “as Author” in the definition of the variable, at run time you can extract this information as the anno-
tation’s public property Author.
By default, this annotation can be used on any method, type, property, or constructor, and as many times as
desired. For example, you could specify multiple authors for a class or even multiple authors for methods on a
class, or both. You can customize these settings and restrict the annotation’s usage, as discussed in “Customizing
Annotation Usage” on page 160.
For now, test this annotation by using it on a newly defined type, such as a new Gosu class. Create the following
class in the com.mycompany package:
package com.guidewire.pl.docexamples.annotations
uses com.guidewire.pl.docexamples.annotations.Author
@Author("A. C. Clarke")
@Author("J. M. Straczynski")
class Spaceship {
You can get annotation information from a class either directly by getting the type from an object at runtime.
First can get an object’s type at runtime using the typeof operator or by getting the Type property from an object.
Next, get its TypeInfo property and call the getAnnotation method, passing your annotation class name directly
as a parameter. The result is a list (java.util.List) containing annotation information objects. For each one of
these, get its Value property and coerce it to your annotation class.
For example, add the example classes from earlier in this topic into your Gosu environment and then paste the
following code into the Gosu Tester:
uses com.guidewire.pl.docexamples.annotations.Author
uses com.guidewire.pl.docexamples.annotations.Spaceship
print("")
print("Get annotations directly from a type, then iterate with a block...")
var annotations2 = Spaceship.Type.TypeInfo.getAnnotation(Author)
annotations2.each( \ a -> print(" Author: " + (a.Value as Author).AuthorName))
For more information about blocks and using collections, see “Gosu Blocks” on page 165 and “Collections” on
page 183.
The default availability is universal. In other words, if no AnnotationUsage attribute is defined on an annotation,
the usage defaults to allow the annotation unlimited times on all parts of a type or class.
However, once any AnnotationUsage annotation is used in an annotation definition, all targets default to None.
After using AnnotationUsage once, Gosu requires you to explicitly specify supported targets using
AnnotationUsage meta-annotations. You can optionally add multiple lines for each type of permitted use.
IMPORTANT The default annotation availability is universal (all parts, many times). As soon as you
use one AnnotationUsage line in the annotation definition, Gosu assumes all targets revert to None.
Explicitly list all permitted usages with AnnotationUsage lines as appropriate.
The annotation class is always in scope. You do not need to fully-qualify the class name or use a uses statement
in files that use it.
Enhancements
Gosu enhancements are a language feature that allows you to augment classes and other types with additional
concrete methods and properties. For example, use enhancements to define additional utility methods on a class
or interface that cannot be directly modified, even code written in Java. You can enhance classes originally
written in Gosu or Java. Enhancing is different from subclassing in important ways. Enhancing a class makes
new methods and properties available to all objects of that enhanced type, not just Gosu code that explicitly
knows about the subclass. Use enhancements to add powerful functionality omitted by the original authors.
This topic includes:
• “Using Enhancements” on page 161
Using Enhancements
Gosu enhancements allow you to augment classes and other types with additional concrete methods and proper-
ties. The most valuable use of this feature is to define additional utility methods on a Java class or interface that
cannot be directly modified. This is most useful if a class’s source code is unavailable, or a given class is final
(cannot be subclassed). Enhancements can be used with interfaces as well as classes, which means you can add
useful methods to interfaces.
Enhancing a class or other type is different from subclassing: enhancing a class makes the new methods and
properties available to all instances of that class, not merely subclass instances. For example, if you add an
enhancement method to the String class, all String instances in Gosu automatically have the additional method.
You can also use enhancements to overcome the language shortcomings of Java or other languages defining a
class or interface. For example, Java-based classes and interfaces can be used from Gosu, but they do not
natively allow use of blocks, which are anonymous functions defined in-line within another function. (See “Gosu
Blocks” on page 165.) Gosu includes many built-in enhancements to commonly-used Java classes in its products
so that any Gosu code can use them.
For example, Gosu extends the Java class java.util.ArrayList so you can use concise Gosu syntax to sort,
find, and map members of a list. These list enhancements add additional methods to Java lists that take Gosu
blocks as parameters. The original Java class does not support blocks because the Java language does not support
blocks. However, these enhancements add utilities without direct modifications to the class. Gosu makes these
additional methods automatically and universally available for all places where Gosu code uses
java.util.ArrayList.
You can also enhance an interface. This does not mean an enhancement can add new methods to the interface
itself. The enhancement does not add new requirements for classes to implement the interface. Instead,
enhancing an interface means that all objects whose class implements the interface now has new methods and
properties. For example, if you enhance the java.util.Collection interface with a new method, all collection
types suddenly have your newly-added method.
This does not go into detail about the built-in enhancements to collections. For reference documentation, see
“Collections” on page 183. If you have not yet learned about Gosu blocks, you may want to first review “Gosu
Blocks” on page 165.
You could even use the method on a value you provide at compile time:
"a string".calculateHash()
Similarly, if the enhancement adds a property called MyProperty to the String type, you could use code such as:
var p = "a string".MyProperty
The new methods and properties all appear in the list of methods that appears if you type a period (.) character in
the Gosu editor. For example, if typing “s1.calculateHash()”, after you type “s1.” the list that appears
displays the calculateHash method as a choice.
You can add new properties as necessary and access the properties on the class/type within Gosu. However, that
does not actually allow you to save state information for the enhancement unless you can do so using variables or
properties that already exist on the enhanced type. See later in this section for more on this topic.
For example, the following enhancement adds one standard method to the basic String class and one property:
package example
Note the use of the syntax “property get” for the method defined as a property.
With this example, use code like the following to get values:
// get an enhancement property:
print("This is my string".myProperty)
Enhanced methods can call other methods internally, as demonstrated with the getPrettyLengthString method,
which calls the built-in String method length().
IMPORTANT Enhancements can create new methods but cannot override existing methods.
print(strlist)
strlist.LastItem = "hello"
print(strlist)
You can add new properties and add property set functions to set those properties. However, in contrast to a class,
enhancements cannot define new variables on the type to store instance data for your enhancement. This limits
most types of state management if you cannot directly change the source code for the enhanced type to add more
variables to the enhanced type. Enhancements cannot add new variables because different types have dramati-
cally different property storage techniques, such as a persistent database storage, Gosu memory storage, or file-
based storage. Enhancements cannot transparently mirror these storage mechanisms.
Also, although enhancements can add properties, enhancements cannot override existing properties.
IMPORTANT Enhancements can add new properties by adding new dynamic property get and set
functions to the type. However, enhancements cannot override property get or set functions. Also,
enhancements cannot create new native variables on the object that would require additional data
storage with the original object. Enhancements cannot override methods either.
For example, to enhance the Report class, you could call it simply:
ReportEnhancement
If the enhancement added methods related to claim financials, you might emphasize the enhancement’s func-
tional purpose by naming the enhancement:
ReportFinancialsEnhancement
Enhancement Packages
Use your own company package to hierarchically group your own code and separate it from built-in types, in
almost all cases. For example, you could define your enhancement with the fully-qualified name
com.mycompany.ReportEnhancement. Even if you are enhancing a built-in type, if at all possible use your own
package for the enhancement class itself.
In only extremely rare cases, you might need to enhance a built-in type and you need to use a protected prop-
erty or method. If so, you might need to define your enhancement in a subpackage of the enhanced type. See
“Modifiers” on page 135 for more information about the protected keyword. However, to avoid namespace
conflicts with built-in types, avoid this approach if possible.
Enhancements on Arrays
To specify the enhanced type for an enhancement on an array type:
• For regular types, use standard array syntax, such as String[].
• For generic types, use the syntax T[], which effectively means all arrays.
Gosu Blocks
Gosu blocks are a special type of function that you can define in-line within another function. You can then pass
that block of code to yet other functions to invoke as appropriate. Blocks are very useful for generalizing algo-
rithms and simplifying interfaces to certain APIs. For example, blocks can simplify tasks related to collections,
such as finding items within or iterating across all items in a collection.
This topic includes:
• “What Are Blocks?” on page 165
• “Basic Block Definition and Invocation” on page 166
• “Variable Scope and Capturing Variables In Blocks” on page 168
• “Argument Type Inference Shortcut In Certain Cases” on page 169
• “Block Type Literals” on page 169
• “Blocks and Collections” on page 171
• “Blocks as Shortcuts for Anonymous Classes” on page 171
ymous classes in Java. However, Gosu blocks provide a concise and clear syntax that makes this feature more
convenient in typical cases.
Blocks are particularly valuable for the following:
• Collection manipulation. Using collection functions such as map and each with Gosu blocks allows concise
easy-to-understand code with powerful and useful behaviors for real-world programming.
• Callbacks. For APIs that wish to use callback functions after an action is complete, blocks provide a straight-
forward mechanism for triggering the callback code.
• Resource control. Blocks can be useful for encapsulating code related to connection management or transac-
tion management.
Gosu code using blocks appropriately can simplify and reduce the size of your Gosu code. However, they can
also be confusing if used too aggressively and use them carefully. If your intended use does not fall into one of
the list categories, reconsider whether to use blocks. There may be a better and more conventional way to solve
the problem. Generally speaking, if you write a method that takes more than one block as a function/method
argument, strongly consider redesigning or refactoring the code.
WARNING Gosu blocks are not always the correct design solution. For example, if you design a func-
tion that takes more than one block as arguments, a general rule is to redesign or refactor your code.
The argument list (argumentList) is a standard function argument list, for example:
x : Number, y : Number
The argument list defines what parameters must be passed to the block. The parameter list uses identical syntax
as parameters to regular functions. However, in some cases you can omit the types of the parameters, such as
passing a block directly into a class method such that the parameter type can be inferred. For examples, see
“Argument Type Inference Shortcut In Certain Cases” on page 169.
The block body (blockBody) can be either of the following:
• a simple expression. This includes anything legal on the right-hand side of an assignment statement. For
example, the following is a simple expression:
"a concatenated string " + "is a simple expression"
• a statement list with one or more statements surrounded by braces and separated by semi-colon characters,
such as the following simple one-statement statement list:
\ x : Number, y : Number -> { return x + y }
For single-statement statement lists, you must explicitly include the brace characters. In particular, note that
variable assignment operations are always statements not expressions. Thus, the following expression is
invalid:
names.each( \ n -> myValue += n )
Instead, change it to the following:
names.each( \ n -> { myValue += n } )
For multiple statements, separate the statements with a semi-colon character. For example:
\ x : Number, y : Number -> { var i = x + y; return i }
The following block multiplies a number with itself, which is known as squaring a number:
var square = \ x : Number-> x * x //no need for braces here
var myResult = square(10) // call the block
IMPORTANT All parameter names in a block definition’s argument list must not conflict with any
existing in-scope variables, including but not limited to local variables.
The Gosu editor displays a block definition’s backslash character as a Greek lambda character. This improves
code appearance and honors the theoretical framework from which blocks derive, called lambda calculus. The
Gosu editor displays the pair of characters -> as an arrow symbol.
For example, you could type the following Gosu block:
var square = \ x : Number -> x * x
In general, the standard Gosu style is to omit all semicolon characters in Gosu at the end of lines. Gosu code is
more readable without optional semicolons. However, if you provide statement lists on one line, such as within
block definitions, use semicolons to separate statements. For other style guidelines, see “General Coding Guide-
lines” on page 279.
Because the statement return "hello blocks" returns a String, that means the block’s return type is String.
IMPORTANT Gosu infers a block’s return type by the returned value of the return statements of the
statement list. If an expression is provided instead of a statement list, Gosu uses the type of the expres-
sion. That type is static (fixed) at compile time although it is not explicitly visible in the code.
2. an open parenthesis
4. a closing parenthesis
For example, suppose you create a Gosu block with no arguments and a simple return statement:
var blockWithStatementBody = \-> { return "hello blocks" }
Because the statement list returns a String, Gosu infers that the block returns a String. The new block is
assigned to a new variable blockWithStatementBody, and the block has a return type of String even though this
fact is not explicit in the code text.
To call this block and assign the result to variable myresult, simply use this code:
var myresult = blockWithStatementBody()
The value of the variable myresult is the String value "hello blocks" after this line executes:
The following example creates a simple block that adds two numbers as parameters and returns the result:
var adder = \ x : Number, y : Number -> { return x + y }
After defining this block, you can call it with code such as:
var mysum = adder(10, 20)
The variable mysum has the type Number and has the value 30 after the line is executed.
You can also implement the same block behavior by using an expression rather than a statement list, which
allows an even more concise syntax:
var adder = \ x : Number, y : Number -> x + y
After the third line is executed, myresult contains the value 20.
A block captures the state of the stack at the point of its declaration, including all variables and the special
symbol this, which represents the current object. For example, the current instance of a Gosu class running a
method.
This capturing feature allows the block to access variables in scope at its definition:
• ...even after being passed as an argument to another function
• ...even after the block returns to the function that defines it
• ...even if some code assigns it to a variable and keeps it around indefinitely
• ...even after the original scope exits (after it finishes)
In other words, each time the block runs, it can access all variables declared in that original scope in which it was
defined. The block can get or set those variables. The values of captured variables are evaluated each time the
block is executed, and can be read or set as desired. Captured variable values are not simply a static snapshot of
their value at the time the block was created.
To illustrate this point further, the following example creates a block that captures a variable (x) from the
surrounding scope. Next, the code that created the block changes the value of x. Only after that change does any
code actually call the block:
// define a local variable, which is captured by a block
var x = 10
// Note: the variable "x" is now SHARED by the block and the surrounding context
The captured variable is effectively shared by the original scope and the block that was created within that
scope. In other words, the block references the variable itself, not merely its original value.
IMPORTANT If accessing variables not defined within the block definition, blocks effectively share
the variable with the context that created it. This is true even if the original scope exited (finished) or its
value has changed. This is a very powerful feature. If you use this feature at all, use it very carefully
and document your assumptions so people who read your code can understand and debug it.
You could instead omit the argument type (String). The map method signature allows Gosu to infer the argument
type in the block because of how the map method is defined.
You could use the more concise code:
var x = new ArrayList<String>(){"a", "b", "c"}
The list method map() is a built-in list enhancement method that takes a block with one argument. That argument
is always the same as the list’s type. Therefore Gosu infers that str must be of type String and the you do not
need to explicitly define the type of arguments nor the return type.
Note: The map method is implemented using a built-in Gosu enhancement of the Java language List class.
For more information, see “Collections” on page 183.
For example, to declare that x is a variable that can contain a block that takes a single String argument and
returns a String value, use this code:
var x( String ) : String
In declarations, you can also optionally use the block keyword, although this is discouraged in declarations:
block( list_of_types ) : return_type
For example, this code declares the same block type as described earlier:
var x : block( String ) : String
For example:
var b = block( String ) : Number
This means that the b variable is assigned a value that is a block type. Since the block type literal is not directly
part of the declaration, the block keyword must be specified.
For example, suppose you want to declare a function that took one argument, which is a block. Suppose the block
takes a single String argument and returns no value. If you want refer to this block by name as myCallback,
define the argument using the syntax:
myCallBack( String ) : void
It might be easier to understand with an actual example. The following Gosu class includes a function that takes
a callback block. The argument is called myCallBack, which is a block that takes a single string argument and
returns no value. The outer function calls that callback function with a String.
package mytest
class test1 {
function myMethod( myCallBack( String ) : void ) {
}
}
For even more concise code, you can omit the argument type “: String” in the in-line block. The block is
defined in-line as an argument to a method whose argument types are already defined. In other words, you can
simply use the following code
var a = new mytest.test1()
a.myMethod( \ s -> print("<contents>" + s + "</contents>") )
You could easily resort the list based on the length of the strings using blocks. Create a block that takes a String
and returns the sort key, which in this case is the string’s length. The built-in list sortBy(...) method handles
the rest of the sorting algorithm and then returns the new sorted array:
var resortedStrings = myStrings.sortBy( \ str -> str.Length() )
These block-based collection methods are implemented using a built-in Gosu enhancement of the Java language
List class. For more information, see “Collections” on page 183.
Gosu Generics
Gosu generics is a language feature that lets you define a class or function as working with many types by
abstracting its behavior across multiple types of objects. This abstraction feature is important because collections
defined with generics can specify what kinds of objects they contain. If you use collections, you can be specific
about what objects are in the collection. You do not need to very general about the type of the contents, such as
using a root type such as Object. However, if designing APIs that can work with different types of objects, you
can write the code only once and it works with different types of collections. In essence, you can generalize class
or methods to work with various types and retain compile-time type safety. Use generics to write statically typed
code that can be abstracted to work with multiple types.
Generics are especially valuable for defining special relationships between arguments to a function and/or its
return values. For example, you can require two arguments to a function to be homogenous collections of the
same type of object and the function returns the same type of collection. Designing APIs to be abstract like that
allows your code and the Gosu language to infer other relationships. For example, an API that returns the first
item in a collection of String objects is always typed as a String. You need not write coercion code with the
syntax “as TYPE” as often if designing your APIs to use generics. Because generics increase how often Gosu can
use type inference, your collection-related code can be easy-to-understand, concise, and type-safe.
Gosu generics are compatible with generics in Java version 1.5, so you can use Java classes designed for Java 1.5
generics or even extend them in Gosu.
For more information about static typing in Gosu, see “More About the Gosu Type System” on page 29.
This topic includes:
• “Gosu Generics Overview” on page 174
• “Using Gosu Generics” on page 175
• “Other Unbounded Generics Wildcards” on page 177
• “Generics and Blocks” on page 178
• “How Generics Help Define Collection APIs” on page 180
• “Multiple Dimensionality Generics” on page 180
• “Generics With Custom ‘Containers’” on page 181
Standard collections can contain a variety of types of objects (they are heterogeneous). If you take an object out
of a collection, typically you must cast it to a desired type or check its type before doing something useful with it.
Without generics, in practice, people tend to design collection-related APIs to work with collections of Object
instances. The Object class is the root class of all non-primitive objects in the Gosu language and also in the Java
language.
Unfortunately, if you use APIs that return collections of type Object, your code must cast (coerce) it to a more
specific type to access properties and methods.
Although casting one value to another type is useful, it is unsafe in some cases and prevents the compiler from
knowing at compile-time whether it succeeds. For example, if the item you extract from the collection is a type
that does not support casting, it fails at run time. For example, casting a String to an Array. This approach to
coding is inconsistent with confirming type problems at compile time. Detecting problems at compile time is
important for reliable mission-critical server applications.
A simple alternative is to define different types of collections/lists that support only homogenous sets of objects
of a certain type, such as a StringList, an IntegerList, or a MyCustomClassList. This provides compile-time
certainty and thus dramatically reduces the chance of type safety issues. However, the downside is more
complexity to make the API work with different types of lists. A Gosu class method that takes a StringList
would need a separate method signature to take an IntegerList. This type of repetitive method signature decla-
ration simply to achieve type safety is time consuming. Additionally, it might be incomplete: if you provide an
API, it cannot predict list of types you do not know about that a consumer of your API wants to use. If only there
were a way to generalize the function so that it would work with all lists, you could provide a generalized (or
generic) function to perform the task.
Suppose you could define a collection with an explicit type of each item. With the angle-bracket notation after
the collection class such as List<Number>, you can specify what types of things the container contains. If you
read aloud, you can translate the bracket notation in English as the word “of”. Thus, in English, the syntax
List<Number> means “a list of numbers”. Even better, suppose there was a way to define function parameters to
work with any type. What if it always returns an object of the same type, or an array of that type, and have such
relationships enforced at compile time? This is what Gosu generics do for you.
Generics provide a way to specify the type of objects in a collection with specificity as you use an API but with
generality as you design an API. At compile time, the Gosu compiler confirm everything has a valid type for the
API. Additionally, Gosu infers types of arguments and return values in many cases so you do not have to do
much coercing values from a root class. For instance, you do not generally need to coerce a variable of type
Object to a more useful specific type. Suppose you take values out of a collection of objects of type MyClass. A
variable that contains an extracted first item in the collection always has type MyClass, not Object. With generics
you do not need to coerce the value to type MyClass before calling methods specific to the MyClass class.
Generics provide the best of generalizability as you design APIs and specificity as you use APIs. Using generics,
your collections-related code can be easy-to-understand, concise, and typesafe.
Gosu generics are compatible with generics implemented in Java version 1.5. You can use Java utility classes
designed for Java 1.5 generics and even extended them in Gosu. There is one exception for Java-Gosu compati-
bility, which is that Gosu does not support the syntax <? super TYPE>. For more information about other similar
features, see “Bounded Wildcards” on page 178.
For extended discussions of generics as implemented in Java, see the book “Java Generics and Collections” by
Maurice Naftalin and Philip Wadler, or the following on-line tutorial:
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
You could create a function that takes a specific type of list, in this case a list of strings:
function printStrings( strs : ArrayList<String> ) {
for( s in strs ) {
print( s )
}
}
If you want to call a method using Gosu generics to take an array list of any type, simply call the method:
r = printStrings(theList)
If Gosu knows the return result type of a function, it can infer the type of other things, which makes your code
more concise:
var strs = new ArrayList<String>(){"a", "ab", "abc"}
var longerStrings = strs.findAll( \ str -> str.length >= 2 )
In the previous example, the resulting value of longerStrings is strongly typed as ArrayList<String>. This is
because Gosu knows the return type of the findAll method called on any array list of String values. If you get
an object from value of longerStrings, it has the correct expected String type, not simply Object.
Using functions defined with generics typically are simple, often even more simple because of Gosu generics.
The return value can be strongly typed to match the exact type of collection you passed into it or one of its
items. For example, return a “list of MyClass objects” or “a MyClass object”, rather than a “list of Object” or just
an Object. Although generics are abstract, using APIs other people defined with generics typically is straightfor-
ward and intuitive.
wide variety of collections: a Collection of MyClass objects, a Collection of Address objects, and so on.
However, any code that extracted items from the collection after an API call would have to add code with a coer-
cion “x as TYPE” if extracting an object from it:
var f = myCollection.iterator.next()
(f as MyClass).myClassMethod()
Note the code “f as MyClass”. That approach typically results in hard-to-read code, since you must manually
add casting to a specific type for a variety of APIs due to this issue. Additionally, it is dangerous because the
actual casting happens at run time and you could make a mistake by casting it to the wrong object. Most impor-
tantly, the casting could fail at run time in some cases if you make other types of errors, rather than identified
and flagged at compile time. Fortunately, with generics this type of casting is not necessary if you use APIs
designed with generics and design any new APIs with generics.
That would allow us to remove the cast (the “as MyClass”) from the previous example:
var a = new ArrayList<MyClass>() { c1, c2, c3 }
...
From quickly looking at the code, you might assume from the text that the first variable is not strongly typed
after removing the cast. However, it is strongly typed at compile time.
If you want to make full use of the language’s ability to use generic types, you have two choices:
• parameterize a class, which means to add generic types to the class definition
• parameterize a method, which means to add generic types to a method definition
Parameterized Classes
If you want a class that always operates with a generic type, define the class with the angle bracket notation
CLASSNAME<GENERIC_TYPE_NAME> in the class definition. By convention, for the GENERIC_TYPE_NAME string, use
a one-letter variable, preferably T. For example, you could define a class MyClass as MyClass<T>.
In the following example, the class Genericstest has one method that returns the first item in a list. Gosu
strongly types the return value to match the type of the items in the collection:
package com.example
uses java.util.ArrayList
class Genericstest<T>
{
// print out (for debugging) and then return the first item in the list, strongly typed
public function PrintAndReturnFirst(aList : ArrayList<T>) : T {
print(aList[0])
return aList[0]
}
}
Now, some other code could use this class and pass it an array list of any type:
var myStrings = new ArrayList<String>(){"a", "abcd", "ab", "abc"}
After this code runs, the value of the variable first is strongly typed as String because of how it used the
method that was defined with generics.
This also works with multiple dimensions of types. Suppose you want to write something that stores key-value
maps. Instead of writing:
class Mymapping {
function put( key : Object, value : Object) {...}
function get( key : Object) : Object {...}
}
Now you can use this class with strongly typed results:
myMap = new Mymapping<String, Integer>
myMap.put("ABC", 29)
theValue = myMap.get("ABC")
The theValue variable is strongly typed at compile time as Integer, not Object.
Within the method definition, the values in angle brackets have special meanings as type names in a parameter-
ized class definition. In this case, the K and V symbols. Use these symbols in method signatures in that class to
represent types in arguments, return values, and even Gosu code inside the method.
You can think about it as at the time the method runs, the symbols K and V are pinned (assigned) to specific types
already. By the time this method runs, some other code created new instances of the parameterized class with
specific types already. The compiler can tell which method to call and what types K and V really represent. In the
earlier example, the concrete types are String (for K) and Integer (for V).
Gosu generics offer this power to define APIs once and abstract the behavior across multiple types. Define your
APIs with the generics and wildcards to generalize your APIs to work with different types of types or collections.
Your code is strongly-typed code at compile time, which improves reliability of code at run time.
Parameterized Methods
You can add a finer granularity of type usage by adding the generic type modifiers to the method, immediately
after the method name. This is called parameterizing the method, or making a polymorphic method with a
generic type.
For example, in the following example, the class is not parameterized but one method is:
package com.example
uses java.util.ArrayList
class Test3
{
// return the last item in the list
public function ReturnLast<T>(a : ArrayList<T>) : T{
Within the method’s Gosu code, the symbol T can be used as a type and this code works automatically, matching
T to the type of the collection passed into it.
For more details about how generics interact with blocks, see “Generics and Blocks” on page 178.
Bounded Wildcards
You can specify advanced types of wildcards if you want to define arguments that work with many types of
collections. However, you can still make some types of assumptions about the object’s type. For example, you
might want to support homogenous collections (all items are of the same type) or perhaps only instances of a
class and its subclasses or subinterfaces.
Suppose you had a custom class Shape. Suppose you want a method to work with collections of circle shapes or
collections of line shapes, where both Circle and Line classes extend the Shape class. For the sake of this
example, assume the collections are always homogenous and never contain a mix of both types.
It might seem like you could define a function like this:
public function DrawMe (circleArray : ArrayList<Shape>)
The function would work if you pass it an object of type ArrayList<Shape>. However, it would not work if you
tried to pass it an ArrayList<Circle>, even though Circle is a subclass of Shape.
Instead, specify support of multiple types of collections while limiting support only to certain types and types
that extend those types. Use the syntax “extends TYPE” after the wildcard character, such as:
<T extends TYPE>
or...
<? extends TYPE>
For example:
public function DrawMe (circleArray : ArrayList<T extends Shape>)
In English, you can read that argument definition as “the parameter circleArray is an ArrayList containing
objects all of the same type, and that type extends the Shape class”.
Although Gosu generics work very similar to generics in the Java language, one other type of bounded wildcard
supported by Java is not supported in Gosu. The supertype bounded wildcard syntax <? super TYPE> is
supported by Java but not by Gosu.
WARNING Gosu does not support the generics syntax for bounded supertypes <? super TYPE>,
which is supported by Java. That syntax is rarely used anyway because the <? extends TYPE> is more
appropriate for typical code.
// call your block. notice that the variable is strongly typed as String, not as Object
var first = getFirstItem(s)
print(first)
Notice that the return result is strongly typed and Gosu infers the appropriate type from the block.
Note the use of the letter T in the enhancement definition and in the method signature:
value(T):Comparable
That syntax means that the argument is a block that takes one argument of type T and returns a Comparable value
(such as an Integer or String).
Suppose you had an array list of strings:
var myStrings = new ArrayList<String>(){"a", "abcd", "ab", "abc"}
You could easily resort the list based on the length of the strings using blocks. Create a block that takes a String
and returns the sort key, in this case the text length. Let the List.sortBy(...) method handle the rest of the
sorting algorithm details and return the new sorted array.
var resortedStrings = myStrings.sortBy( \ str -> str.Length() as Integer )
It is important to understand that this example omitted the type of the block argument str. You do not have to
type:
var resortedStrings = myStrings.sortBy( \ str : String -> str.Length() as Integer )
Type inference in cases like this valuable for easy-to-understand and concise Gosu code that uses generics.
IMPORTANT If you define a block as an argument to a method, you can omit the argument types in
the block in some cases. Omit the type if Gosu can infer the type from the arguments required of that
method. Omitting the type in cases in which you can do so leads to concise easy-to-read code.
Practical examples of this approach, including the method definitions of the built-in sortBy method are shown in
the following section, “How Generics Help Define Collection APIs” on page 180.
For extensive information about similar APIs with blocks, see “Gosu Blocks” on page 165. For specific exam-
ples of built-in APIs that use generics with blocks, see “Collections” on page 183.
If you want to print the contents, you could print them with:
resortedStrings.each( \ str -> print( str ) )
This concise syntax is possible because the sortBy method is defined a single time with Gosu generics.
It uses the wildcard features of Gosu generics to work with all lists of type T, where T could be any type of object,
not just built-in types. The method is defined as a Gosu enhancement to all List objects. This means that the
method automatically works with all Java objects of that class from Gosu code, although the method is not
defined in Java. Enhancement definitions look similar to classes. The enhancement for the sortBy method looks
like:
enhancement GWBaseListEnhancement<T> : java.util.List<T>
...
...
public function sortBy( value(T):Comparable ) : java.util.List<T> {
...
}
}
That means that it works with all lists of type T, and the symbol T is treated as the type of the collection. Conse-
quently, the sortBy method uses the type of collection (in the earlier example, an array list of String objects). If
the collection is a list of String objects, method must takes a comparison function (a block) that takes a String
object as an argument and returns a Comparable object. The symbol T is used again in the return result, which is
a list that has the same type passed into it.
IMPORTANT For a reference of extremely powerful collection-related APIs that use blocks and Gosu
generics, see “Collections” on page 183
have type Long, and values that have type String. In some sense, a Map is a two-dimensional collection, and you
can define a map to have a specific type:
Map<Long, String> contacts = new HashMap<Long, String>()
Suppose you want to define an API that worked with multiple types of maps. However, the API would return a
value from the map and it would be ideal if the return value was strongly typed based on the type of the map. You
could use a 2-dimensional generics with wildcards, to define the method signature:
public function GetHighestValue( themap : Map<K,V>) : V
The argument themap has type Map and specifies two type wildcards (single capital letter) separated by commas.
In this case, assume the first one represents the type of the key (K) and the second one represents the type of the
value (V). Because it uses the V again in the return value type, the Gosu compiler makes assumptions about rela-
tionships between the type of map passed in and the return value.
For example, suppose you pass the earlier example map of type <Long, String> to this API. The compiler
knows that the method returns a String value. It knows this because of the two uses of V in the method signature,
both as parameter and as return value.
Abstract Example
Suppose you want to write something that stores key-value maps. Instead of writing:
class Mymapping {
function put( key : Object, value : Object) {...}
function get( key : Object) : Object {...}
}
Now you can use this class with strongly typed results:
myMap = new Mymapping<String, Integer>
myMap.put("ABC", 29)
theValue = myMap.get("ABC")
Real-world Example
Suppose you were writing a program for an automotive manufacturing company and want to track vehicles
within different factories during production. Suppose you want to represent cars with a Car object, trucks with a
Truck object, vans with a Van object, and these all derive from a root class Vehicle.
You could create some sort of custom container object called Factory that does not derive from the built-in
collection classes. For the purpose of this example, assume that each factory only contains one type of vehicle. A
FactoryGroup could contain multiple Car objects, or multiple Truck objects, or multiple Van objects.
Suppose you need APIs to work with all of the following types:
• a FactoryGroup containing one or more Car objects
• a FactoryGroup containing one or more Truck objects
• a FactoryGroup containing one or more Van objects
Perhaps you want an API that returns all vehicles in the last step in a multi-step manufacturing process. You
could define the API could be defined as:
public function GetLastStepVehicles(groupofvehicles FactoryGroup<T>) : FactoryGroup<T>
Because the method uses generics, it works with all types of FactoryGroup objects. Because both the same letter
T appears more than once in the method signature, this defines parallelism that tells Gosu about relationships
between arguments and/or return values.
The definition of this method could be understood in English as:
“The method GetLastStepVehicles takes one argument that is a factory group containing any one vehicle
type. It returns another factory group that is guaranteed to contain the identical type of vehicles as passed into
the method.”
Alternatively, you could define your API with bounded wildcards for the type:
public function GetLastStepVehicles(groupofvehicles FactoryGroup<? extends Vehicle>) : FactoryGroup<T>
Using this approach might allow your code to make more assumptions about the type of objects in the collection.
It also prevents some coding errors, such as accidentally passing FactoryGroup<String> or
FactoryGroup<Integer>, which fail at compile time. You can find out about your coding errors quickly.
If you want to make code like this, you also need to tell the Gosu compiler that your class is a container class that
supports generics. Simply add the bracket notation in the definition of the class, and use a capital letter to repre-
sent the type of the class. For example, instead of typing:
public class MyFactory
...you would instead define your class as a container class supporting generics using the syntax:
public class MyFactory<T>
You also could let your class support multiple dimensions similar to how the Map class works with two dimen-
tions. See “Multiple Dimensionality Generics” on page 180. You could define your class abstracted across
multiple types, separated by commas:
public class MyClass<K, V>
Collections
The collection and list classes used frequently in Gosu rely on the Java language’s collection classes. However,
there are important differences because of built-in enhancements to these classes that use Gosu blocks, anony-
mous in-line defined functions that are not directly supported in the Java language. Combining Gosu’s enhance-
ment and block features permits concise easy-to-understand Gosu code that manipulates collections. With a
single line of code, you can loop across collection items and perform actions on each items, extract information
from each item, or sort items.
Related topics:
• “Gosu Blocks” on page 165.
• “Gosu Generics” on page 173.
• “Enhancements” on page 161.
IMPORTANT This topic assumes understanding of blocks and generics. To understand how generics
enable the enhancement-based APIs, see “How Generics Help Define Collection APIs” on page 180.
Basic Lists
Lists in Gosu inherit from the Java interface java.util.List and its common subclasses such
java.util.ArrayList.
Creating a List
To create a list with nothing it, specify the type of object it contains in brackets using generics notation, such as
in this example using an ArrayList of String objects:
var myemptylist = new ArrayList<String>()
For more information about generics, see “Gosu Generics” on page 173.
In many cases you might want to initialize (load) it with data. Gosu has special features that allow a natural
syntax for initializing lists similar to initializing arrays.
For example, the following is an example simple array initializer:
var s2 = new String[ ] {"This", "is", "a", "test."}
The type of s3 is java.util.ArrayList<String> (a list of String objects) because all list members have the type
String.
Gosu infers the type of the List to be the least upper bound of the components of the list. In the simple case
above, the type of the variable x at compile time is List<String>. If you pass different types of objects, Gosu
finds the most specific type that includes all of the items in the list.
If the types implement interfaces, Gosu attempts to preserve commonality of interface support in the list type.
This ensures your list acts as expected with APIs that rely on support for the interface. In some cases, the
resulting type is a compound type, which combines a class and one or more interfaces into a single type. For
example, the following code initializes an int and a double:
var s = {0, 3.4}
You can write this in Gosu instead in the more natural index syntax using Gosu shortcuts:
var strs = {"a", "ab", "abc"}
strs[0] = "b"
var firstStr = strs[0]
Gosu does not automatically resize lists using this syntax. If a list has only three items, the following code does
not work:
strs[3] = "b" // index number 2 is the higest supported number
Gosu provides additional initializer syntax for both lists and maps similar to Gosu’s compact initializer syntax
for arrays.
Basic HashMaps
Maps in Gosu inherit from the Java class java.util.HashMap.
Creating a HashMap
To create an empty map, specify the type of objects it contains in brackets using generics notation. For example,
define a HashMap that maps a String object to another String object:
var emptyMap = new HashMap<String, String>()
For more information about generics, see “Gosu Generics” on page 173.
In many cases you might want to initialize (load) it with data. Gosu has special features that allow a natural
syntax for initializing maps similar to initializing arrays and lists.
For example, the following code creates a new HashMap where "a" and "c" are keys, whose values are "b" and
"d" respectively
var strMap = new HashMap<String, String>(){"a" -> "b", "c" -> "d"}
This syntax makes it easy to declare static final data structures of this type within Gosu, and with easier-to-read
code than the equivalent code would be in Java.
You can write this instead in the more natural index syntax using Gosu shortcuts:
var strs = new HashMap<String, String>(){"a" -> "b", "c" -> "d"}
strs["e"] = "f"
var valueForE = strs["e"]
Because the type of the map is explicit in the function, callers of this function can use an initializer expression
without specifying the type name or even the keyword new. This does not mean that the list is untyped. The list is
statically typed but it is optional to declare explicitly because it is redundant.
For example, you could initialize a java.util.Map and call this function with verbose code like:
printMap( new Map<String, String>() {"a" -> "b", "c" -> "d"} )
Instead, simply type the following code and use type inference for concise code:
printMap( {"a" -> "b", "c" -> "d"} )
Gosu permits this last example as valid and typesafe. Gosu infers the type of the List to be the least upper bound
of the components of the list. In the simple case above, the type of the variable x at compile time is
List<String>. If you pass different types of objects, Gosu finds the most specific type that includes all of the
items in the list.
If the types implement interfaces, Gosu attempts to preserve commonality of interface support in the list type.
This ensures your list acts as expected with APIs that rely on support for the interface. In some cases, the
resulting type is a compound type, which combines a class and one or more interfaces into a single type. For
example, the following code initializes an int and a double:
var s = {"hello" -> 0, "there" -> 3.4}
The resulting type of s is HashMap<String, java.lang.Comparable & java.lang.Number>. This means that it
is a map with two generic parameters:
• String
• The compound type of the class Number and the interface Comparable.
Note: The Number class does not implement the interface Comparable. If it did, then the type of s would
simply be Map<String, java.lang.Number>. However, since it does not implement that interface, but both
int and double implement that interface, Gosu assigns the compound type that includes the interfaces that
they have in common.
The nameArray variable contains an array whose length is exactly the same as the length of myArrayofBooks.
The first item is the value myArrayofBooks[0].Name, the second item is the value of myArrayofBooks[1].Name,
and so on.
For another example, suppose you wanted to get a list of the groups a user belongs to so you can display the
display names of each group. Suppose a User object contains a MemberGroups property that returns a read-only
array of groups that the user belongs to. In other words, the Gosu syntax user.MemberGroups returns an array of
Group objects, each one of which has a DisplayName property. If you want to get the display names from each
group, use the following Gosu code
user.MemberGroups*.DisplayName
Because MemberGroups is an array, Gosu expands the array by the DisplayName property on the Group compo-
nent type. The result is an array of the names of all the Groups to which the user belongs. The type is String[].
The result might look like the following:
["GroupName1", "GroupName2", "GroupName14", "GroupName22"]
The expansion operator works with methods also. Gosu uses the type that the method returns to determine how to
expand it:
• if the original object is an array, Gosu creates an expanded array
• if the original method is a list, Gosu creates an expanded list
The following example calls a method on the String component of the List of String objects. It generates the
list of initials, in other words the first character in each word.
var s = {"Fred", "Garvin"}
Array expansion is valuable if you need a single one-dimensional array or list through which you can iterate.
Also, there are various enhancement methods for manipulating arrays and lists. For details, see “Enhancement
Reference for Collections and Related Types” on page 188.
Important notes about the expansion operator:
• The generated array or list itself is always read-only from Gosu. You can never assign values to elements
within the array, such as setting nameArray[0].
• The expansion operator *. works only for array expansion, never standard property accessing.
• When using the *. expansion operator, only component type properties are accessible.
• When using the *. expansion operator, array properties are never accessible.
• The expansion operator applies not only to arrays, but to any Iterable type and all Iterator types and it
preserves the type of array/list. For instance, if you apply the *. operator to a List, the result is a List. Other-
wise, the expansion behavior is the same as with arrays.
class Family {
var _members : String[] as Members
}
print(allMembers)
The following table lists some of the collection enhancements. The letter T refers to the type of the collection.
The syntax <T> relates to the feature Gosu generics, discussed in “Gosu Generics” on page 173. For example,
suppose the argument is listed as:
conditionBlock(T):Boolean
This means the argument is a block. That block must take exactly one argument of the list’s type (T) and returns
a Boolean. Similarly, where the letter Q occurs, this represents another type. The text at the beginning (in that
example, conditionBlock is a parameter that is a block and its name describes the block’s purpose.
Note: If a type letter wildcard like T or Q appears more than once in arguments or return result, it must repre-
sent the same type each time that letter is used.
Method/Property Description
Count Returns the number of elements in the Iterable
single() If there is only one element in the Iterable, that value is returned. Otherwise an
IllegalStateException is thrown.
toCollection() If this Iterable is already of type Collection, return it. Otherwise, copy all values out of this Iter-
able into a new Collection.
Note: The collection enhancement methods for sorting and ordering rely on comparison
methods built into the Java interface java.lang.Comparable. Because of this, these
methods do not sort String values in a locale-sensitive way.
orderByDescending(proj) Returns a new List<T> reverse ordered by the given value. Note that this is different than
sortByDescending(), which is retained on List<T> and which sorts in place.
Note: The collection enhancement methods for sorting and ordering rely on comparison
methods built into the Java interface java.lang.Comparable. Because of this, these
methods do not sort String values in a locale-sensitive way.
Methods on List<T>
The following table lists the available methods on List<T>.
Methods on Set<T>
The following table lists the available methods on Set<T>.
The following subsections describe the most common uses of these collection enhancement methods.
The value of longerStrings is {"ab", "abc"}. The expression str.length >= 2 is true for both of them.
The firstWhere method takes a block that returns true or false and return the first elements for which the
block returns true. The following example demonstrates how to find the first item that matches the criteria:
var strs = new ArrayList<String>(){"a", "ab", "abc"}
var firstLongerStr = strs.firstWhere( \ str -> str.length >= 2 )
The value of firstLongerStr is "ab", since "ab" is the first element in the list for which str.length >= 2 eval-
uates as true.
If firstWhere finds no matching items, it returns null.
Similarly, there is a lastWhere method that finds the last item that matche the condition, and returns null if none
are found.
Sorting Collections
Suppose you had an array list of strings:
var myStrings = new ArrayList<String>(){"a", "abcd", "ab", "abc"}
You can easily resort the list by the length of the String values using blocks. Create a block that takes a String
and returns the sort key, which in this case is the number of characters of the parameter. Let the
List.sortBy(...) method handle the rest of the details of the sorting and return the new sorted array as the
result.
var resortedStrings = myStrings.sortBy( \ str -> str.Length )
If you want to print the contents, you could print them with:
resortedStrings.each( \ str -> print( str ) )
Similarly, you can use the sortByDescending function, which is the same except that it sorts in the opposite
order.
For both of these methods, the block must return a comparable value. Comparable values include Integer, a
String, or any other values that can be compared with the “>” or “<” (greater than or less than) operators.
In some cases, comparison among your list objects might be less straightforward. You might require more
complex Gosu code to compare two items in the list. In such cases, use the more general sort method simply
called sort. The sort method takes a block that takes two elements and returns true if the first element comes
before the second, or otherwise returns false. The earlier sorting example could be written as:
var strs = new ArrayList<String>(){"a", "abc", "ab"}
var sortedStrs = strs.sort( \ str1, str2 -> str1.length < str2.length )
Although this method is powerful, in most cases code is more concise and easier to understand if you use the
sortBy or sortByDescending methods instead of the sort method.
Note: The collection enhancement methods for sorting and ordering rely on comparison methods built into
the Java interface java.lang.Comparable. Because of this, these methods do not sort String values in a
locale-sensitive way.
The value of lengthsOnly at the end of this code is an array with elements: 1, 1, 2, 2, 3, 4.
In this example, the map method takes a block that is a simple function taking one String and returning its
length. However, notice that it did not explicitly set the type of the block’s argument called myStrings. However,
this is not an untyped argument, at compile time it is statically typed as a String argument. This is implicit
because the array list is specified as a list of String using the generics syntax ArrayList<String>.
Some Gosu collection-related code has concise syntax because collection methods use Gosu generics. Generics
allow methods such as map to naturally define the relationship of types in arguments, return values, and the type
of objects in the collection. In this case, the array list is an array list of strings. The map method takes a block that
must have exactly one argument and it must be a String. Gosu knows the block must take a String argument
so the type can be omitted. Gosu can simply infer the argument type to allow flexible concise code with all the
safety of statically-typed code.
The type of the lengthsOnly variable also uses type inference and is statically typed. Because the block returns
an int, the result type of the function must be an int. Because of this, lengthsOnly is statically typed at compile
time to an array of integers even though the type name is not explicit in the code. Specifying the type is optional,
and it is good Gosu coding style to use type inference for simple cases like this.
As you can see, this is a simple and powerful way to do some types of repeated actions with collections. This
conciseness can be good or bad, depending on the context of the code. In some cases, it might be better to assign
the return value of map to a variable and call the each method on it. This is especially true if you still need the
array of lengths even after printing them. For example:
var myStrings = new ArrayList<String>(){"a", "b", "bb", "ab", "abc", "abcd"}
var strLengths = myStrings.map( \ str -> str.length )
strLengths.each( \ len -> print( len ) )
Partitioning Collections
Blocks are also useful with the partition method. This method takes a list and creates a new java.util.Map of
key/value pairs. The block takes an item from the original list as an argument and returns a value. To perform this
task for all input list items, the map keys are results from the block with the input list. Each key points to the
input list items that produced that value.
For example, suppose you want take a String list and partition it into a Map containing the lengths of each
String value. Suppose the set of input values were the following:
var myStrings = new ArrayList<String>(){"a", "b", "bb", "ab", "abc", "abcd"}
Each key points to a list of all input String values with that length. You could use this one line of Gosu code:
var lengthsToStringsMap = myStrings.partition( \ str:String -> str.length )
In other words:
• key 1 points to a list of two values, "a" and "b"
• key 2 points to a list of two values "bb" and "ab"
• key 3 points to a list with a single value, "abc"
• key 4 points to a list with a single value, "abcd"
As you can tell from this example, you can make concise and easy-to-read Gosu code with powerful results.
Also, note the resulting Map is statically typed using type inference.
You can improve your performance if you are sure the output of your block for each list element is always
unique. The indirection of having each value wrapped within a list using the partition method is unnecessary
because there is always a single item in every list. For faster performance in the case in which you know block
return results are unique, use the partitionUniquely method.
For example:
var myStrings = new ArrayList<String>(){"bb", "a", "abcd", "abc"}
var lengthsToStringsMap = myStrings.partitionUniquely( \ str:String -> str.length )
The result Map has values that are single items not lists:
Map { 1 "a", 2 "bb", 3 "abc", 4 "abcd" }
The value of claimsById is a Map of claim publicID values to the claims they represent.
If more than one element of the list has the same calculated value for the attribute, the method throws a runtime
exception.
Next, pass this block to the flatMap method to generate a single list of all notes on the claim:
var allNotes = myClaim.Exposures.flatMap( \ e -> e.Notes )
This generates a single list of notes (on instance of List<Note> in generics notation) containing all the notes on
all the exposures on the claim.
This method is similar to the Gosu feature called array expansion (see “Array Expansion” on page 74). However,
it is available on all collections as well as arrays, and flatMap method generate different extracted arrays dynam-
ically using a Gosu block that you provide. Your block can perform any arbitrary and potentially-complex calcu-
lation during the flat mapping process.
XML files describe complex structured data in a text-based format with strict syntax for easy data interchange.
For more information on the Extensible Markup Language, refer to the World Wide Web Consortium web page
http://www.w3.org/XML. Gosu can read or write any XML document. If you have an associated XSD to define
the document structure, Gosu parses the XML using the schema. This produces a statically-typed tree of XML
elements with structured data. Also, during parsing, Gosu can validate the XML against the schema. You can
also manipulate XML or generate XML without an XSD file, but use XSDs if possible. Without an XSD, your
XML elements do not get programming shortcuts (Gosu properties on each element) or intelligent static typing.
This topic includes:
• “Manipulating XML Overview” on page 196
• “Introduction to XmlElement” on page 196
• “Exporting XML Data” on page 200
• “Parsing XML Data into an XML Element” on page 201
• “Creating Many QNames in the Same Namespace” on page 203
• “XSD-based Properties and Types” on page 204
• “Getting Data From an XML Element” on page 211
• “Simple Values” on page 214
• “Access the Nillness of an Element” on page 217
• “Automatic Creation of Intermediary Elements” on page 218
• “Default/Fixed Attribute Values” on page 218
• “Substitution Group Hierarchies” on page 219
• “Element Sorting for XSD-based Elements” on page 220
• “Built-in Schemas” on page 222
• “Schema Access Type” on page 223
Introduction to XmlElement
The main class that represents an XML element is the class XmlElement.
An XmlElement object consists of the following items (and only the following items):
• The element name (as a QName). The element’s name is not simply a String value. It is a fully-qualified
name (a QName). A QName represents a more advanced definition of a name than a simple String value.
Gosu uses the standard Java way to specify a QName: the class javax.xml.namespace.QName. A QName
object contains the following components:
• A String value that represents the local part (also called the localPart)
• A String value that represents the namespace URI that the local part of the name is defined within. For
example, a namespace might have the value: http://www.w3.org/2001/XMLSchema-instance
• A suggested prefix name if Gosu later serializes this element. (This prefix is not guaranteed upon serial-
ization, since there may be conflicts.)
For example, you might see in an XML file an element name with the syntax of two parts separated by a
colon, such as veh:root. The root part of the name is the local part. The prefix veh in this example indicates
that the XML document (earlier in the file) a declared namespace and a shortcut name (the prefix veh) to rep-
resent the full URI.
For example, consider the following XML document:
<?xml version="1.0"?>
<veh:root xmlns:veh="http://mycompany.com/schema/vehiclexsd">
<veh:childelement/>
</veh:root>
The following things are true about this XML document:
• The root element of the document has the name root within the namespace http://mycompany.com/schema/
vehiclexsd.
• The text xmlns:veh text followed by the URI means that later in the XML document, elements can use the
namespace shortcut veh: to represent the longer URI: http://mycompany.com/schema/vehiclexsd.
• The root element has one child element, whose name is childelement within the namespace http://
mycompany.com/schema/vehiclexsd. However, this XML document specifies the namespace not with the full
URI but with the shortcut prefix veh followed by the colon (and then followed by the local part).
There are three constructors for QName:
• QName constructor specifying the namespace URI, local part, and suggested prefix.
QName(String namespaceURI, String localPart, String prefix)
• QName constructor specifying the namespace URI and local part (suggested prefix is implicitly empty).
QName(String namespaceURI, String localPart)
• QName constructor specifying the local part only (the namespace and URL are implicitly empty)
QName(String localPart)
You can set the namespace in the QName to the empty namespace, which technically is the constant
javax.xml.XMLConstants.NULL_NS_URI. The recommended approach for creating QName objects in the
empty namespace is to use the QName constructor that does not take a namespace argument.
To create multiple QName objects easily in the same namespace, you can use the optional utility class called
XmlNamespace. For details, see “Creating Many QNames in the Same Namespace” on page 203.
When constructing an XmlElement, the name is strictly required and must be non-empty.
Note: QNames are used for other purposes in Gosu XML APIs. For example, attributes on an element are
names defined within a namespace, even if it is the default namespace for the XML document or the empty
namespace. Gosu natively represents both attribute names and element names as QNames.
• A backing type instance. Each element contains a reference to a Gosu type that represents this specific
element. To get the backing type instance, get the TypeInstance property from the element. For XML
elements that Gosu created based on an XSD, Gosu sets this backing type information automatically so it can
be used in a typesafe manner.
When constructing an XmlElement, an explicit backing type is optional. If you are constructing the element
from an XSD, Gosu sets the backing type automatically based on the subclass of XmlElement.
You can use XmlElement essentially as untyped nodes, in other words with no explicit XSD for your data for-
mat. If you are not using an XSD and do not provide a backing type, Gosu uses the default backing type
gw.xml.xsd.w3c.xmlschema.types.complex.AnyType. All valid backing types are subclass of that AnyType
type. See “Getting Data From an XML Element” on page 211 for related information
The type instance of an XML element is responsible for most of the element’s behavior but does not contain
the element’s name. You can sometimes ignore the division of labor between an XmlElement and its backing
type instance. If you are using an XSD, this distinction is useful and sometimes critical. For more informa-
tion, see “Getting Data From an XML Element” on page 211.
• The nillness of the element.XML has a concept of whether an element is nil. This is not exactly same as
being null. An element can be nil (and must have no child elements) but still have attributes. Additionally,
an XSD can define whether an element is nillable, which means that element is allowed to be nil. For more
information, see “Access the Nillness of an Element” on page 217.
To summarize, the XmlElement instance contains the properties shown in the following table.
XmlElement
property Type Description
QName QName A read-only property that returns the element’s
QName.
Namespace XmlNamespace Returns an XmlNamespace object that represents the
element’s namespace
TypeInstance gw.xsd.w3c.xmlschema.types.complex.AnyType Returns the element's backing type instance
or any subclass of that class
Nillness boolean Specifies whether this element is nil, which is
an XML concept that is not the same as being
null. See “Access the Nillness of an Element”
on page 217
IMPORTANT If you are accessing these properties on an XSD-based element, you must use a dollar
sign prefix for the property name. See “Dollar Sign Prefix For Some Properties When Using XSD
Types” on page 199
To create a basic XmlElement, simply pass the element name to the constructor as either a QName or a String. The
constructor on XmlElement that takes a String is a convenience method. The String constructor is equivalent
passing a new QName with that String as the one-argument constructor to QName. In other words, the name-
space and prefix in the QName are null if you use the String constructor on XmlElement.
The following code creates an in-memory Gosu object that represents an XML element <Root> in the empty
namespace:
var el = new XmlElement( "Root" )
In this case, the el.TypeInstance property returns an instance of the default type
gw.xsd.w3c.xmlschema.types.complex.AnyType. If you instantiate a type instance, typically you would use
more specific subclass of AnyType, either an XSD-based type or a simple type.
For a more complex example, the following Gosu code creates a new XmlElement without an XSD, and adds a
child element:
uses gw.xml.XmlElement
uses javax.xml.namespace.QName
e.addChild(e2)
e.print()
Technically, the Gosu object that represent the element does not directly contain the child elements or the text
content. It is the backing type instance for each element which contains the text content. However, in practice
this distinction is not typically necessary to remember.
An element can contain either child elements or simple values, but never both at the same time. This distinction
is important particularly for XSD-based types. Gosu handles properties on elements differently depending on
whether it contains a simple value or is a type that can contain child elements.
IMPORTANT Element contain child elements or simple values, but never both at the same time.
Dollar Sign Prefix For Some Properties When Using XSD Types
For the some properties that the documentation mentions, Gosu provides access directly from the XML element
even though the actual implementation internally is on the backing type instance.
If an element is not an XSD-based element, simply access the properties directly, such as element.Children.
However, if you are using an XSD type, you must prefix the dollar sign ($) before any property name. This
convention prevents ambiguity with properties defined on the XSD type or on the type instance that backs that
type. For example, suppose the XSD could define a an element’s child element literally named Children. There
would unfortunately be two similar properties with the same name. Gosu prevents ambiguity by requiring the
special properties to have a dollar sign prefix if and only if the element is XSD-based:
• To access the children of an XSD-based element, use the syntax element.$Children.
• To access the a custom child element named Children as defined by the XSD, use the syntax
element.Children. This is a non-recommended name due to the ambiguity, but Gosu has no problem with it.
You may not have control over the XSD format that you are using, so Gosu must disambiguate them.
Notes about this convention:
• This convention only applies to properties defined on XSD-based types.
• It does not apply to methods.
• It does not apply to non-XSD-based XML elements.
For example, suppose you use the root class XmlElement directly with no XSD to manipulate an untyped graph
of XML nodes. In that case, you can omit the dollar sign because the property names are not ambiguous. There
are no XSD types so there is no overlap in namespace.
This affects the following type instance property names that appear on an XML element, listed with their dollar
sign prefix:
• $Attributes
• $Class
• $Children
• $Namespace
• $NamespaceContext
• $Comment
• $QName
• $Text
• $TypeInstance
• $SimpleValue
• $Value - only for elements with an XSD-defined simple content
• $Nil - only for XSD-defined nillable elements. See “Access the Nillness of an Element” on page 217.
IMPORTANT It is important to understand that some special property names on an XML element
include a dollar sign prefix if and only if the XML element is an XSD type. If you create an
XmlElement element directly (not a subclass), it is not an XSD type. It is an untyped node that uses the
default type instance (an instance of the type AnyType). In such cases, there is no dollar sign prefix
because there is no ambiguity between properties that are really part of the type instance, rather than on
the XSD type.
IMPORTANT Although the asUTFString method is helpful for debugging use, the asUTFString
method is not the best way to export XML safely to external systems. In general, use the bytes method
to get an array of bytes. If your code sends or stores XML with a transport that only understands char-
acter data (not byte data), always Base64 encode the array of bytes. See the example earlier in this
section for the bytes method.
For all serializations, be sure to test your code with non-English characters. In other words, be sure to test with
characters with high Unicode code points.
WARNING Always test your XML serialization and integration code with non-English characters.
For all of these methods, you can customize serialization by optionally passing an XmlSerializationOptions
instance as another parameter at the end of the parameter list. The serialization options object contains the
following properties:
• Comments - Boolean. If true, exports each element’s comments. The default is true.
• Pretty - Boolean. If true, Gosu attempts to improve visual layout of the XML with indenting and line sepa-
rators. The default is true. If you set this to false, then Gosu ignores the values of the Indent and
LineSeparator properties.
• Indent - String. Specifies the String to export for each level of hierarchy. The default is two spaces.
• LineSeparator - String. Sets the line separator. The default is newline (ASCII 10).
• Sort - Boolean. If true, ensures that the order of children elements of each element match the XSD. The
default is true. This is particularly important for sequences. This feature only has an effect on an element if it
is based on an XSD type. If the entire graph of XmlElement objects contains no XSD-based elements, this
property has no effect. If a graph of XML objects contains a mix of XSD and non-XSD-based elements, this
feature only applies to the XSD-based elements. This is true independent of whether the root node is an
XSD-based element.
• XmlDeclaration - Returns whether to write the XML declaration at the top of the file.
For example, the following example creates an element, then adds an element comment. Next, it demonstrates
printing the element with the default settings (with comments) and how to customize the output to omit
comments.
uses gw.xml.XmlSerializationOptions
// create an element
var a = new com.guidewire.pl.docexamples.gosu.xml.simpleelement.MyElement()
// add a comment
a.$Comment = "Hello I am a comment"
Note that all serialization APIs generate XML data for the entire XML hierarchy with that element at the root.
If you are using an XSD, call the parse method directly on your XSD-based node, which is a subclass of
XmlElement. For example:
var a = com.guidewire.pl.docexamples.gosu.xml.demoattributes.Element1.parse(xmlDataString)
The following table lists the parsing methods (for details of XmlParseOptions, see “Referencing Additional
Schemas During Parsing” on page 202):
To see how and why you would use this, suppose you have the following two schemas:
The XSD ImportXSD1.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:ImportXSD1"
xmlns:ImportXSD1="urn:ImportXSD1">
<xsd:element name="ElementFromSchema1" type="ImportXSD1:TypeFromSchema1"/>
<xsd:complexType name="TypeFromSchema1"/>
</xsd:schema>
Notice that the ImportXSD2 XSD extends a type that the ImportXSD1 defines. This is analogous to saying the
ImportXSD2 type called TypeFromSchema2 is like a subclass of the ImportXSD1 type called TypeFromSchema1.
The following code fails (throws exceptions) because the ImportXSD1 references the schema type
ImportXSD2:TypeFromSchema2 and Gosu cannot find it anywhere in the current schema.
var schema2 = com.guidewire.pl.docexamples.gosu.xml.importxsd2.util.SchemaAccess
// parse an element defined in the the first schema, but pass an extension to that
// that type that the second schema defines. THIS FAILS without using the AdditionalSchemas feature
var element = ElementFromSchema1.parse(xsdtext)
The main problem is that the ImportXSD1 XSD type does not directly know about the existence of the schema
called ImportXSD2 even though it extends one of its types.
To make it work, set the AdditionalSchemas property of the XmlParseOptions object to a list containing one or
more SchemaAccess objects. In other words, the following XML parsing code succeeds:
var schema2 = com.guidewire.pl.docexamples.gosu.xml.importxsd2.util.SchemaAccess
var options = new gw.xml.XmlParseOptions() { :AdditionalSchemas = { schema2 } }
// parse an element defined in the the first schema, but pass an extension to that
// that type that the second schema defines. To do this, it requires using the XmlParseOptions
var element = ElementFromSchema1.parse(xsdtext, options)
To simplify this process, Gosu includes a utility class called gw.xml.XmlNamespace. It represents a namespace
URI and a suggested prefix. In other words, it is like a QName but without the local part.
There are two ways to use this:
• Create an XmlNamespace directly and call its qualify method and pass the local part String. For example:
uses gw.xml.XmlNamespace
var ns = new XmlNamespace("namespaceURI","prefix")
var e = new XmlElement(ns.qualify("localPartName"))
• Reuse the namespace of an already-created XML element. To get the namespace from an XML element
instance, get its NameSpace property. Then, simply call the qualify method and pass the local part String:
// create a new XML element
var xml = new XmlElement( new QName( "namespaceURI", "localPart", "prefix" ) )
// shorthand for reusing the namespaceURI and prefix from the previously-created element
var xml2 = new XmlElement( xml.Namespace.qualify( "localPart2" ) )
• an element definition causes Gosu to create a type that describes the element
• a type definition causes Gosu to create a type that describes the type (for example, a new complex type)
• an attribute definition causes Gosu to create a type that describes the attribute
For example, suppose an XSD declares a new top-level simple type that represents a phone number. Suppose
there are 3 element definitions that reference this new simple type in different contexts for phone numbers, such
as work number, home numbers, and cell number. In this example, Gosu creates:
• 1 type that represents the phone number simple type
• 3 types that represent the individual element definitions that reference the phone number
From Gosu, when you are creating objects or setting properties on elements, it is important to know which type
you want to use. In some cases, you might be able to do what you want in more than one way, although one way
might be easier to read. See “XSD Generated Type Examples” on page 208 for examples that illustrate this point
further.
Also remember that if you have a reference to the element, you can always reference the backing type. For
example, for an element, you can reference the backing type instance using the $TypeInstance property. See
“XSD Generated Type Examples” on page 208 for examples of this.
The rightmost column indicates (for properties only) whether the property becomes a list property if it can appear
more than once. If it says “Yes”, the property has type java.util.List parameterized on what type it is when it
is singular. For example, suppose a child element is declared in the XSD with the type xsd:int:
• If its maxOccurs is 1, the property’s type is Integer
• If its maxOccurs is greater than 1, the property’s type is List<Integer>, which means a list of integers
There are other circumstances in which a property becomes a list. For example, suppose there is a XSD choice
(<xsd:choice>) in an XSD that has maxOccurs attribute value greater than 1. Any child elements become list
properties. For example, if the choice defines child elements with names "elementA" and "elementB", Gosu
creates properties called ElementA and ElementB, both declared as lists. Be aware that Gosu exposes shortcuts
for inserting items, see “Automatic Insertion into Lists” on page 209.
Notes about generated types containing the text anonymous in the fully qualified type name:
• Although the package includes the word anonymous, this does not imply that these elements have no defined
names. The important quality that distinguishes these types is that the object is defined at a lower level than
the top level of the schema. By analogy, this is similar to how Gosu and Java define inner classes within the
namespace of another class.
• There are several rows that contain a reference to the path from root as the placeholder text PathFromRoot.
The path from root is a generated name that embeds the path from the root of the XSD, with names separated
by underscore characters. The intermediate layers may be element names or group names. See each row for
examples.
For every child element with either (1) simple type or (2) complex type and a simple content
It is a common pattern to convert a simpleType at a later time to simpleContent simply to add attributes to an element with
a simple type. To support this common pattern, Gosu creates two properties ChildName and ChildName_elem for every child
element with either a simply type or both a complex type and simple content. The one with the _elem suffix contains the ele-
ment object instance. The property without the _elem suffix contains the element value. Because of this design, if you later
decide to add attributes to a simpleType element, your XML code requires no changes simply because of this change.
For every child element with complex type and no simple content
XSD Generated Types: Element Type Instances Compared to Backing Type Instances
Suppose you have a XSD that defines one phone number simple type and multiple elements that use that
simple type.
The XSD might look like the following:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="cell" type="phone"/>
<xsd:element name="work" type="phone"/>
<xsd:element name="home" type="phone"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="phone">
<xsd:sequence>
<xsd:element name="areaCode" type="xsd:string"/>
<xsd:element name="mainNumber" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Suppose you want to create and assign the phone numbers. There are multiple ways to do this.
If you want to create three different phone numbers, use code like this:
var e = new schema.Person()
e.Cell.AreaCode = "415"
e.Cell.MainNumber = "555-1213"
e.Work.AreaCode = "416"
e.Work.MainNumber = "555-1214"
e.Home.AreaCode = "417"
e.Home.MainNumber = "555-1215"
In contrast, you want to create one phone number to use in multiple elements, you might use code like this:
var e = new schema.Person()
e.Cell.$TypeInstance = p
e.Work.$TypeInstance = p
e.Home.$TypeInstance = p
e.Cell = p // SYNTAX ERROR: cannot assign complex type instance to element type instance
e.Work = p // SYNTAX ERROR: cannot assign complex type instance to element type instance
e.Home = p // SYNTAX ERROR: cannot assign complex type instance to element type instance
Additionally, different element-based types can be mutually incompatible for assignment even if they are asso-
ciated with the XSD type definition. For example:
var e = new schema.Person()
e.Cell = e.Work // SYNTAX ERROR: cannot assign one element type to a different element type
If the list does not exist yet for a list property at all, Gosu creates the list upon the first insertion.
In other words, suppose an element contains child elements that represent an address and the child element has
the name Address. If the XSD declares the element could exist more than once, the element.Address property is
a list of addresses. The following code creates a new Address:
element.Address[0] = new my.package.xsdname.elements.Address()
IMPORTANT If you use XSDs, Gosu automatically creates intermediate XML elements as needed.
Use this feature to significantly improve the readability of your XML-related Gosu code.
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
This outputs:
Before insertion: 0
After insertion: 3
<?xml version="1.0"?>
<Element1>
<Child1>0</Child1>
<Child1>1</Child1>
<Child1>2</Child1>
</Element1>
print( "----------" )
xml.Child1 = null
xml.Child2 = { 1, 2, 3, 4 }
xml.print()
Gosu exposes properties and methods on the XML type instances for you to get child elements or simple value.
It is important to note that XML elements contain two basic types of content:
• child elements
• simple value
An element can contain either child elements or a simple value, but not both at the same time.
IMPORTANT Elements contain child elements or text, but never both at the same time.
• the element named Child1 has no explicit type. This means the default type applies, which is xsd:anyType.
• the element named Child2 has the type xsd:int. This means that by definition, this element must contain an
integer value. Integer is a simple type. Without the integer value (if it were empty or null), any XML for this
document would be invalid according to the XSD.
If you have a reference to an XML element of a simple type, you can set its value by setting its SimpleValue
property. (If you are using an XSD, add the dollar sign prefix: $SimpleValue)
To set a simple value (like an integer value for an element), there are several approaches:
• Set the value in the SimpleValue property, to a subclass of XmlSimpleValue. This allows you to directly
create the simple value that Gosu stores in the pre-serialized graph of XML elements. If it is on an XSD type,
specify the property name with the dollar sign prefix: $SimpleValue. To create an instance of the
XmlSimpleValue of the appropriate type, call static methods on the XmlSimpleValue type with method names
that start with make.... For example, call the makeIntInstance method and pass it an Integer. It returns an
XmlSimpleValue instance that represents an integer, and internally contains an integer. In memory, Gosu
stores this information as a non-serialized value. Only during serialization of the XML, such as exporting into
a byte array or using the debugging print method, does Gosu serialize the XmlSimpleValue into bytes or
encoded text. For a full reference of all the simple value methods and all their variants, see “Simple Values”
on page 214.
• To create simple text content (text simple value), set the element’s Text property to a String value. If it is on
an XSD type, specify the property name with the dollar sign prefix: $Text.
• If you are using an XSD, you can set the natural value in the Value property. If it is on an XSD type, specify
the property name with the dollar sign prefix: $Value. For example, use natural-looking code like
e.$Value = 5. If you are using an XSD and have non-text content, this approach tends to result in more
natural-looking Gosu code than creating instances of XmlSimpleValue.
• If you are using an XSD, Gosu provides a simple syntax to get and set child values with simple types. For
example, set numbers and dates from an element’s parent element using natural syntax using the child
element name as a property accessor. This lets you easily access the child element’s simple value with very
readable code. For example, e.AutoCost = 5. See “XSD-based Properties and Types” on page 204.
The following Gosu code adds two child elements, sets the value of an element using the Value property and the
SimpleValue property, and then prints the results. In this example, we use XSD types, so we must specify the
special property names with the dollar sign prefix: $Value and $SimpleValue.
uses gw.xml.XmlSimpleValue
// create a new CHILD element that is legal in the XSD, and add it as child
var c1 = new com.guidewire.pl.docexamples.gosu.xml.demochildprops.anonymous.elements.Element1_Child1()
e.addChild(c1)
// create a new CHILD element that is legal in the XSD, and add it as child
var c2 = new com.guidewire.pl.docexamples.gosu.xml.demochildprops.anonymous.elements.Element1_Child2()
print("before set: " + c2.$Value) // prints "null" -- it is uninitialized
c2.$SimpleValue = XmlSimpleValue.makeIntInstance(5)
print("after set with $SimpleValue: " + c2.$Value)
c2.$Value = 7
print("after set with $Value: " + c2.$Value)
print("")
print("")
e.print()
Children 2[com.guidewire.pl.docexamples.gosu.xml.demochildprops.anonymous.elements.Element1_Child1
instance, com.guidewire.pl.docexamples.gosu.xml.demochildprops.anonymous.elements.Element1_Child2
instance]
<?xml version="1.0"?>
<Element1>
<Child1/>
<Child2>7</Child2>
</Element1>
Note that the Child2 element contains the integer as text data in the serialized XML export. Gosu does not seri-
alize the simple types to bytes (or a String) until serialization. In this example, the final print statement is what
serializes the element and all its subelements.
// Get a child using a QName, and "reuse" the namespace of a previous node
var getChild2FromQName = e.getChild(getChild1.Namespace.qualify("Child2"))
print(getChild2FromQName.asUTFString())
• removeChildren( QName ) : List<XmlElement> - Removes the child with the specified QName name. There
is an alternate method signature that takes a String value for the local part name. For that method, Gosu
internally creates a QName with an empty namespace and the specified local part name.
Attributes
Attributes are additional metadata on an element. For example, in the following example an element has the
color and size attributes:
<myelement color="blue" size="huge">
Every type instance contains its attributes, which are XmlSimpleValue instances specified by a name (a QName).
For more information about simple values, see “Simple Values” on page 214.
Each XmlElement object contains the following methods and properties
• AttributeNames property - Gets a set of QName objects. The property type is java.util.Set<QName>.
• getAttributeSimpleValue( QName )- Get attribute simple value by its name, specified as a QName. Returns
a XmlSimpleValue object. There is an alternate method signature that takes a String instead of a QName, and
it assumes an empty namespace.
• getAttributeValue( QName ) : String - Get attribute value by its name, specified as a QName. Returns a
String object. There is an alternate method signature that takes a String instead of a QName, and it assumes
an empty namespace.
• setAttributeSimpleValue( QName , XmlSimpleValue ) - Set attribute simple value by its name (as a
QName) and its value (as a XmlSimpleValue object). There is an alternate method signature that takes a
String instead of a QName, and it assumes an empty namespace.
• setAttributeValue( QName , String ) - Set attribute value by its name (as a QName) and its value (as a
XmlSimpleValue object). There is an alternate method signature that takes a String instead of a QName, and
it assumes an empty namespace.
Using the previous example, the following code gets and sets the attributes:
myelement.setAttributeValue("color", XmlSimpleValue.makeStringInstance("blue"))
var s = myelement.getAttributeValue("size")
Generally speaking, if you use XSDs for your elements, for typical use do not use these APIs. Instead, use the
shortcuts that Gosu adds. They provide a natural and concise syntax for getting and setting attributes. For details,
see “XSD-based Properties and Types” on page 204.
Simple Values
Gosu represents the XML format simple values with the gw.xml.XmlSimpleValue type. An XmlSimpleValue is a
Gosu object that encapsulates a value and the logic to serialize that value to XML. However, until serialization
occurs, Gosu may internally store it in a format other than java.lang.String.
IMPORTANT For more information about the role of simple values in Gosu XML APIs, see “Getting
Data From an XML Element” on page 211.
For example, XML represents hexadecimal-encoded binary data using the XSD type xsd:hexBinary. Gosu
represents an xsd:hexBinary value with an XmlSimpleValue whose backing storage is an array of bytes
(byte[]), one byte for each byte of binary data. Only when any Gosu code serializes the XML element does
Gosu convert the byte array to hexadecimal digits.
The following properties are provided by XmlSimpleValue:
• GosuValueType - the IType of the GosuValue
• GosuValue - the type-specific Gosu value (for example, a javax.xml.namespace.QName for an xsd:QName)
• StringValue - a string representation of the simple value. This may not be the string that is actually serialized
(such as in the case of a QName)
The following table lists static methods on the XmlSimpleValue type that create XmlSimpleValue instances of
various types.
any type derived by union of (T1, T2,... Tn) greatest common supertype of (T1, T2,... Tn)
Facet Validation
A facet is a characteristic of a data type that restricts possible values. For example, setting a minimum value or
matching a specific regular expression.
Gosu represents each facet as an element. Each facet element has a fixed attribute that is a Boolean value. All the
facets for a simple type collectively define the set of legal values for that simple type.
Most schema facets are validated at property setter time. A few facets are not validated until serialization time to
allow incremental construction of lists at runtime. This mostly affects facets relating to lengths of lists, and those
that validate QNames. Gosu cannot validate QName objects at property setting time because there is not enough
information available. Also, the XML Schema specification recommends against applying facets to QNames at
all.
Example:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Element1">
<xsd:complexType>
<xsd:attribute name="Attr1" type="AttrType"/>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="AttrType">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="5"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Code:
var xml = new schema.Element1()
xml.Attr1 = 3 // works
xml.Attr1 = 6 // fails with exception
Output:
gw.xml.XmlSimpleValueException: Value '6' violated one or more facet constraints
of simple type definition: value must be no greater than 5
WARNING For XSD-based elements not marked as nillable, this property is unsupported. In the Gosu
editor, if you attempt to use the $Nil property, Gosu generates a deprecation warning.
Setting this property on an element to true affects whether upon serialization Gosu adds an xsi:nil attribute on
the element. Getting this property returns the state of that flag (true or false).
Note that nillability is an aspect of elements (and only XSD-based elements), rather than an aspect of the XSD
type itself. For more on the distinction between XmlElement and its backing type, see “Introduction to XmlEle-
ment” on page 196 in the Gosu Reference Guide
For example, consider the following XSD:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Element1" type="xsd:int" nillable="true"/>
</xsd:schema>
This prints:
<?xml version="1.0"?>
<Element1 xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
IMPORTANT If you use XSDs, Gosu automatically creates intermediate XML elements as needed.
Use this feature to significantly improve the readability of your XML-related Gosu code.
This prints:
Before assignment: null
After assignment: schema.anonymous.elements.Element1_Child1 instance
</xsd:schema>
Code:
var xml = new schema.Root()
xml.Person[0].Name = "jsmith"
xml.Person[0].Os = Linux
xml.Person[1].Name = "aanderson"
for ( person in xml.Person ) {
print( "${person.Name} (${person.Location}) -> ${person.Os}" )
}
xml.print()
Output:
jsmith (San Mateo) -> Linux
aanderson (San Mateo) -> Windows
<?xml version="1.0"?>
<root>
<person os="Linux">
<name>jsmith</name>
</person>
<person>
<name>aanderson</name>
</person>
</root>
Code:
var xml = new schema.Customer()
xml.Address = new schema.UKAddress()
xml.print()
Output:
<?xml version="1.0"?>
<Customer>
<UKAddress/>
</Customer>
The XML Schema specification requires that the XSD type of a substitution group member must be a subtype of
the XSD type of its substitution group head. The reason the example above works is because UKAddress,
USAddress and Address are all of the type xsd:anyType (the default when there is no explicit type).
Code:
var xml = new schema.Element1()
xml.Child2 = 2
xml.Child1 = 1
xml.Child3 = 3
xml.print()
Output:
<?xml version="1.0"?>
<Element1>
<Child1>1</Child1>
<Child2>2</Child2>
<Child3>3</Child3>
</Element1>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Code:
var xml = new schema.Element1()
xml.A = 5
xml.B = 5
xml.C = 5
xml.print()
print( "----------" )
xml.Q = 5
xml.print()
Output:
<?xml version="1.0"?>
<Element1>
<A>5</A>
<B>5</B>
<C>5</C>
</Element1>
----------
<?xml version="1.0"?>
<Element1>
<B>5</B>
<C>5</C>
<A>5</A>
<Q>5</Q>
</Element1>
Code:
var xml = new schema.Element1()
xml.A = 5
xml.B = 5
xml.C = 5
xml.print()
print( "----------" )
Output:
<?xml version="1.0"?>
<Element1>
<A>5</A>
<B>5</B>
<C>5</C>
</Element1>
----------
<?xml version="1.0"?>
<Element1>
<C>5</C>
<B>5</B>
<A>5</A>
</Element1>
Code:
var xml = new schema.Element1()
xml.C = 5
xml.A = 5
xml.B = 5
xml.print()
Output:
<?xml version="1.0"?>
<Element1>
<A>5</A>
<B>5</B>
<C>5</C>
</Element1>
Built-in Schemas
Gosu includes several XSDs in the gw.xsd.* package. The following table lists the built-in XSDs.
The XML XSD, which defines the attributes that begin with the xml: prefix, such gw.xsd.w3c.xml
as xml:lang.
XML Schema XSD, which is the XSD that defines the format of an XSD. See “The gw.xsd.w3c.xmlschema.Schema
XSD that Defines an XSD (The Metaschema)” on page 223.
Output:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Element1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Child" type="Type1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="Type1"/>
</xsd:schema>
There is no way to inject a schema into the type system at run time.
This prints:
Element1
Element2
Element3
The following example uses the XSD of XSDs (see “The XSD that Defines an XSD (The Metaschema)” on
page 223) to print a list of primitive schema types:
var schema = gw.xsd.w3c.xmlschema.util.SchemaAccess.Schema
print( schema.SimpleType.where( \ s ->s.Restriction.Base.LocalPart == "anySimpleType" ).map(
\ s ->s.Name ) )
Output:
[string, boolean, float, double, decimal, duration, dateTime, time, date, gYearMonth,
gYear, gMonthDay, gDay, gMonth, hexBinary, base64Binary, anyURI, QName, NOTATION]
The APIs described in this topic generate the entire XML graph.
Gosu code can import web services (SOAP APIs) from external systems and call these services as a SOAP client
(an API consumer). The Gosu language handles all aspects of object serialization, object deserialization, basic
authentication, and SOAP fault handling.
This topic includes:
• “Consuming WS-I Web Service Overview” on page 225
• “Adding WS-I Configuration Options” on page 230
• “One-Way Methods” on page 233
• “Asynchronous Methods” on page 233
One of the big differences between WS-I and older styles of web services is how the client and server encodes
API parameters and return results.
An older style of web services is called Remote Procedure Call encoded (RPCE) web services. The bulk of the
incoming and outgoing data are encoded in a special way that does not conform to XSD files. Many older
systems use RPCE web services, but there are major downsides with this approach. Most notably, the encoding is
specific to remote procedure calls, so it is difficult to validate XML data in RPC encoded responses. It would be
more convenient to use standard XML validators which rely on XSDs to define the structure of the main content.
When you use the WS-I standards, you can use the alternative encoding called Document Literal encoding
(document/literal). The document-literal-encoded SOAP message contains a complete XML document for
each method argument and return value. The schema for each of these documents is an industry-standard XSD
file. The WSDL that describes how to talk to the published WS-I service includes a complete XSD describing the
format of the embedded XML document. The outer message is very simple, and the inner XML document
contains all of the complexity. Anything that an XSD can define becomes a valid payload or return value.
The WS-I standard supports a mode called RPC Literal (RPC/literal) instead of Document Literal. Despite the
similarity in name, WS-I RPC Literal mode is not closely related to RPC encoding. Gosu supports this WS-I
RPC Literal mode for Gosu web service client code. However, it does so by automatically and transparently
converting any WSDL for RPC Literal mode into WSDL for Document Literal mode. The focus of the Gosu
documentation for WS-I web services is the support for Document Literal encoding.
// -- set the web service endpoint URL for the web service WSDL --
var urlStr = "http://www.aGreatWebService.com/GreatWebService?wsdl"
// -- set the location in your file system for the web service WSDL --
var loc = "/wsi/remote/GreatWebService"
The first long string (urlStr) is the URL to the web service WSDL. The second long string (loc) is the path on
your file system where the fetched WSDL is stored. You can run your version of the preceding sample Gosu code
in the Gosu Tester.
• Asynchronous round trip methods (send the request and immediately return to the caller, and check later to
see if the request finished). See “Asynchronous Methods” on page 233.
• One-way methods, which indicate a method defined to have no SOAP response at all. See “One-Way
Methods” on page 233.
The name of MyService becomes lowercase myservice in the package hierarchy for the XML objects because
the Gosu convention for package names is lowercase. There are other name transformations as Gosu imports
types from XSDs. For details, see “Normalization of Gosu Generated XSD-based Names” on page 207.
The structure of a WSDL comprises the following:
• One or more services
• For each service, one or more ports
A port represents a protocol or other context that might change how the WSDL defines that service. For
example, methods might be defined differently for different versions of SOAP, or an additional method might
be added for some ports. WSDL might define one port for SOAP 1.1 clients, one port for SOAP 1.2 clients,
one port for HTTP non-SOAP access, and so on. See discussion later in this topic for what happens if multi-
ple ports exist in the WSDL.
• For each port, one or more methods
A method, also called an operation or action, performs a task and optionally returns a result. The WSDL
includes XML schemas (XSDs), or it imports other WSDL or XSD files. Their purposes are to describe the
data for each method argument type and each method return type.
Suppose the WSDL looks like the following:
<wsdl>
<types>
<schema>
<import schemaLocation="yourschema.xsd"/>
<!-- now define various operations (API methods) in the WSDL ... -->
The details of the web service APIs are omitted in this example WSDL. Assume the web service contains exactly
one service called SayHello, and that service contains one method called helloWorld. Let us assume for this first
example that the method takes no arguments, returns no value, and is published with no authentication or security
requirements.
In Gosu, you can call the remote service represented by the WSDL using code such as:
// get a reference to the service in the namespace of the
var service = new example.pl.gs.wsic.myservice.SayHello()
Of course, real APIs need to transfer data also. In our example WSDL, notice that the WSDL refers a secondary
schema called yourschema.xsd.
Add any additional XSD into the web_service_name.wsdl.resources subdirectory.
Let us suppose the contents of your yourschema.xsd file looks like the following:
<schema>
<element name="Root" type="xsd:int"/>
</schema>
Note that the element name is "root" and it contains a simple type (int). This XSD represents the format of an
element for this web service. The web service could declare a <root> element as a method argument or return
type.
Now let us suppose there is another method in the SayHello service called doAction and this method takes one
argument that is a <root> element.
In Gosu, you can call the remote service represented by the WSDL using code similar to the following:
// get a reference to the service
var service = new ws.myservice.SayHello()
// create an XML document from the WSDL using the Gosu XML API
var x = new ws.myservice.Root()
The package names are different if you place your WSDL file in a different part of the package hierarchy.
For each web service API call, Gosu first evaluates the method parameters. Internally, Gosu serializes the root
XmlElement instance and its child elements into XML raw data using the associated XSD data from the WSDL.
Next, Gosu sends the resulting XML document to the web service. In the SOAP response, the main data is an
XML document, whose schema is contained in (or referenced by) the WSDL.
The NORMALIZED_SERVICE_NAME name of the package is the name of the service as defined by the WSDL, with capi-
talization and conflict resolution as necessary. For example, if there are two services in the WSDL named Report
and Echo, then the API types are in the location
example.pl.gs.wsic.myservice.Report
example.pl.gs.wsic.myservice.Echo
Gosu chooses a default port for each service. If there is a SOAP 1.2 version, Gosu prefers that version.
Additionally, Gosu provides the ability to explicitly choose a port. For example, if there is a SOAP 1.1 port and a
SOAP 1.2 port, you could explicitly reference one of those choices. Gosu creates all the types for your web
service ports within the ports subpackage, with types based on the name of each port in the WSDL:
ROOT_PACKAGE.WSDL_NAME_NORMALIZED.ports.SERVICE_AND_PORT_NAME
The SERVICE_AND_PORT_NAME is the service name, followed by an underscore, followed by the port name.
For example, suppose the ports are called p1 and p2 and the service is called Report. Gosu creates types within
the following packages:
example.pl.gs.wsic.myservice.ports.Report_p1
example.pl.gs.wsic.myservice.ports.Report_p2
Additionally, if the port name happens to begin with the service name, Gosu removes the duplicate service name
before constructing the Gosu type. For example, if the ports are called ReportP1, and helloP2, Gosu creates
types within the following packages:
example.pl.gs.wsic.myservice.ports.Report_P1 // NOTE: it is not Report_ReportP1
example.pl.gs.wsic.myservice.ports.Report_helloP2 // not a duplicate, so Gosu does not remove "Hello"
Each one of those hierarchies would include method names for that port for that service.
The WSDL configuration object has properties that add or change authentication and security settings. The
WsdlConfig object itself is not an XML object (it is not based on XmlElement), but some of its subobjects are
defined as XML objects. Fortunately, in typical code you do not need to really think about that difference.
Instead, simply use a straightforward syntax to set authentication and security parameters. The following
subtopics describe WsdlConfig object properties that you can set on the WSDL configuration object.
Note: For XSD-generated types, if you set a property several levels down in the hierarchy, Gosu adds any
intermediate XML elements if they did not already exist. This makes your XML-related code look concise.
See also “Automatic Creation of Intermediary Elements” on page 218 in the Gosu Reference Guide.
HTTP Authentication
To add simple HTTP authentication to API request, use the basic HTTP authentication object at the path as
follows. Suppose api is a reference to a SOAP API that you have already instantiated with the new operator. The
properties on which to set the name and password are on the object:
api.Config.Http.Authentication.Basic
That object has a Username property for the user name and a Password property for the password. Set those two
values with the desired user name and password.
For example:
service.Config.Http.Authentication.Basic.Username = "jms"
service.Config.Http.Authentication.Basic.Password = "b5"
Setting a Timeout
To set the timeout value (in milliseconds), set the CallTimeout property on the WsdlConfig object for that API
reference.
For example:
// get a reference to the service in the package namespace of the WSDL
var service = new example.gosu.wsi.myservice.SayHello()
in the stream. For example, you might implement encryption this way. Alternatively, some transformations might
require getting all the bytes in the stream before you can begin to output any transformed bytes. Digital signa-
tures would be an example of this approach. You may you use multiple types of transformations. Remember that
the order of them is important. For example, an encryption layer followed by a digital signature is a different
output stream of bytes than applying the digital signature and then the encryption.
Similarly, getting a response from a SOAP client request might require transformations to understand the
response. If the external system added a digital signature and then encrypted the XML response, you need to first
decrypt the response, and then validate the digital signature with your keystore.
The standard approach for implementing these additional security layers is the Java utility WSS4J, but you can
use other utilities as needed. The WSS4J utility includes support for the WSS security standard.
Outbound Security
To add a transformation to your outgoing request, set the RequestTransform property on the WsdlConfig object
for your API reference. The value of this property is a Gosu block that takes an input stream (InputStream) as an
argument and returns another input stream. Your block can do anything it needs to do to transform the data.
Similarly, to transform the response, set the ResponseTransform property on the WsdlConfig object for your API
reference.
The following simple example shows you could implement a transform of the byte stream. In this example, the
transform is an XOR (exclusive OR) transformation on each byte. In this simple example, simply running the
transformation again decodes the request.
The following code implements a service that applies the transform to any input stream. The code that actually
implements the transform is as follows. This is a web service that you can use to test this request.
The class defines a static variable that contains a field called _xorTransform that does the transformation.
package gw.xml.ws
uses java.io.ByteArrayInputStream
uses gw.util.StreamUtil
uses java.io.InputStream
class WsiTransformService {
The following code connects to the web service and applies this transform on outgoing requests and the reply.
package gw.xml.ws
uses gw.testharness.TestBase
uses gw.testharness.RunLevel
uses org.xml.sax.SAXParseException
@RunLevel( NONE )
class WsiTransform {
function testTransform() {
var ws = new wsi.MyService.WsiTransformTestService()
ws.Config.RequestTransform = WsiTransformTestService._xorTransform
ws.Config.ResponseTransform = WsiTransformTestService._xorTransform
One-Way Methods
A typical WS-I method invocation has two parts: the SOAP request, and the SOAP response. Additionally, WS-I
supports a concept called one-way methods. A one-way method is a method defined in the WSDL to provide no
SOAP response at all. The transport layer (HTTP) may send a response back to the client, however, but it
contains no SOAP response.
Gosu fully supports calling one-way methods. Your web service client code does not have to do anything special
to handle one-way methods. Gosu handles them automatically if the WSDL specifies a method this way.
IMPORTANT Be careful not to confuse one-way methods with asychronous methods. For more infor-
mation about asynchronous methods, see “Asynchronous Methods” on page 233.
Asynchronous Methods
Gosu supports optional asynchronous calls to web services. Gosu exposes alternate web service methods signa-
tures on the service with the async_ prefix. Gosu does not generate the additional method signature if the method
is a one-way method. The asynchronous method variants return an AsyncResponse object. Use that object with a
polling design pattern (check regularly whether it is done) the choose to get results later (synchronously in rela-
tion to the calling code).
See the introductory comments in “Consuming WS-I Web Service Overview” on page 225 for related informa-
tion about the basic types of connections for a method.
IMPORTANT Be careful not to confuse one-way methods with asychronous methods. For more infor-
mation about one-way methods, see “One-Way Methods” on page 233.
// Call the **asynchronous** version of the same method -- note the "async_" prefix to the method
var a = ws.async_GetCityWeatherByZIP("94114")
// by default, the async request does NOT start automatically. You must start it with
// the start() method.
a.start()
print ("in a real program, you would check the result possibly MUCH later...")
You can write Gosu code that uses Java types. Gosu code can instantiate Java types, access properties of Java
types and call methods of Java types.
If you are considering writing Java code for your Gosu to call, consider instead writing that code directly in
Gosu. Remember that from Gosu, you can do everything Java can do, including directly call existing Java classes
and Java libraries. You can even write Gosu code enhancements that add properties and methods to Java types,
and the new members are accessible from all Gosu code.
This topic describes how to write and deploy Java code to work with Gosu, and how to call it from Gosu.
IMPORTANT This topic does not discuss differences between the syntax of Gosu and Java. See “Gosu
Introduction” on page 13 and “Notable Differences Between Gosu and Java” on page 37.
IMPORTANT This topic does not focus on differences between the syntax of Gosu and Java. For that
information, refer to the topic “Gosu Introduction” on page 13 and “Notable Differences Between
Gosu and Java” on page 37.
Gosu does not have an equivalent of the static import feature of Java 1.5, which allows you to omit the characters
“Math.”.
This is only a syntax difference for using static members from Gosu (independent of whether the type is imple-
mented in Gosu or Java). If you are writing Gosu code that calls static members of Java types, this does not affect
how you write your Java code.
Next, choose a directory for your .gsp program and copy the Echo.class file to a subdirectory that mirrors the
package of the class. For example, create an empty Gosu program file at this path:
MyDocuments/Gosu/Echo/Echo.gsp
Because the package is gw.doc.examples, add your Java class file to this location:
MyDocuments/Gosu/Echo/gsrc/gw/doc/examples/Echo.class
e.PrintStrings("hello", "world")
print (fromJava)
• Similar to the rules for get, the method name starts with is and takes no arguments and returns a Boolean
value, Gosu exposes this as a property accessor (a getter). The property name matches the original method
but without the prefix is. For example, suppose the Java method signature is isVisible(). Gosu exposes this
a property get function for the property named Visible.
If there is a setter and a getter, Gosu makes the property readable and writable. If the setter is absent, Gosu makes
the property read-only. If the getter is absent, Gosu makes the property write-only.
For example, create and compile this Java class:
package gw.doc.examples;
//Constructor #1 - no arguments
public Circle() {
}
//Constructor #2
public Circle( int dRadius ) {
_radius = dRadius;
}
// from Java these are METHODS that begin with get, set, is
// from Gosu these are PROPERTY accessors
// For GET/IS, the method must take 0 args and return a value
public void isMethod1 () {
System.out.print("running Java METHOD isMethod1() \n");
}
public double getMethod2 (double a, double b) {
System.out.print("running Java METHOD isMethod2() \n");
return 1;
}
// For SET, the method must take 1 args and return void
public void setMethod3 () {
System.out.print("running Java METHOD setMethod3() \n");
}
public double setMethod4 (double a, double b) {
System.out.print("running Java METHOD setMethod4() \n");
return 1;
}
The following Gosu code uses this Java class. Note which Java methods become property accessors and which
ones do not.
// instatiate the class with the constructor that takes an argument
var c = new gw.doc.examples.Circle(10)
// Use natural property syntax to SET GOSU PROPERTIES. In Java, this was a method.
c.Radius = 10
// the following would be syntax errors if you uncomment. They are not writable (no setter method)
// c.Area = 3
// c.Circumference = 4
// c.Round = false
// These Java methods do not convert to properties (wrong number of arguments or wrong type)
c.isMethod1()
var temp2 = c.getMethod2(1,2)
c.setMethod3()
var temp4 = c.setMethod4(8,9)
Interfaces
Gosu classes can directly implement Java interfaces.
Gosu interfaces can directly extend Java interfaces.
Enumerations
Gosu can directly use Java enumerations.
Annotations
Gosu can directly use Java annotations.
Java Primitives
Gosu supports the following primitive types: int, char, byte, short, long, float, double, boolean, and the
special value that means an empty object value: null. This is the full set that Java supports, and the Gosu
versions are fully compatible with the Java primitives, in both directions.
Additionally, every Gosu primitive type (other than the special value null) has an equivalent object type defined
in Java. This is the same as in Java. For example, for int there is the java.lang.Integer type that descends
from the Object class. This category of object types that represent the equivalent of primitive types are called
boxed primitive types. In contrast, primitive types are also called unboxed primitives. In most cases, Gosu
converts between boxed and unboxed primitive as needed for typical use. However, they are slightly different
types, just as in Java, and on rare occasion these differences are important.
In both Gosu and Java, the language primitive types like int and boolean work differently from objects (descen-
dents of the root Object class). For example:
WARNING Java classes you deploy must never have a fully-qualified package name that starts with
"com.guidewire." because that interferes with class loading behavior.
3. Internal classes.
If the class is an internal class, then the class delegate loads.
WARNING Java code you deploy must never access any internal classes other than supported classes
and documented APIs. Using internal classes is dangerous and unsupported.
Gosu Templates
Gosu includes a native template system. Templates are text with embedded Gosu code within a larger block of
text. The embedded Gosu code optionally can calculate a value and export the result as text in the location the
code appears in the template text.
This topic includes:
• “Template Overview” on page 243
• “Using Template Files” on page 245
• “Template Export Formats” on page 249
Template Overview
Templates are text with embedded Gosu code within a larger block of text. The embedded Gosu code optionally
can calculate a value and export the result as text in the location the code appears in the template text. There are
two mechanisms to use Gosu templates:
• Template syntax inside text literals. Inside your Gosu code, use template syntax for an inline String literal
values with embedded Gosu expressions. Gosu template syntax combines static text that you provide with
dynamic Gosu code that executes at run time and returns a result. Gosu uses the result of the Gosu expression
to output the dynamic output at run time as a String value.
• Separate template files. Define Gosu templates as separate files that you can execute from other code to
perform actions and generate output. If you use separate template files, there are additional features you can
use such as passing custom parameters to your template. For more details, see “Using Template Files” on
page 245.
The simplest way to use to templates is to embed Gosu expressions that evaluate at run time and generate text in
the place of the embedded Gosu expressions.
Template Expressions
Use the following syntax to embed a Gosu expression in String text:
${ EXPRESSION }
For example, suppose you want to display text with some calculation in the middle of the text:
var mycalc = 1 + 1
var s = "One plus one equals " + mycalc + "."
Instead of this multiple-line code, embed the calculation directly in the String as a template:
var s = "One plus one equals ${ 1 + 1 }."
Gosu runs your template expression at run time. The expression can include variables or dynamic calculations
that return a value:
var s1 = "One plus one equals ${ myVariable }."
var s2 = "The total is ${ myVariable.calculateMyTotal() }."
At compile time, Gosu uses the built-in type checking system to ensure the embedded expression is valid and
type safe.
If the expression does not return a value of type String, Gosu attempts to coerce the result to the type String.
With a String literal in your code, if you want to use these to indicate template tags, do not need to escape these
special characters.
If you want either of those two special two-character sequences actually in your String (not as a template tag),
escape the first character of that sequence. To escape a character, add a backslash character immediately before
it. For example:
• To define a variable containing the non-template text "Hello${There":
var s = "Hello\${There"
• To define a variable containing the non-template text "Hello<%There":
var s = "Hello\<%There"
If you use the initial character on its own (the next character would not indicate a special tag), you do not need to
escape it. For example:
This creates a String with the following value, including quote signs:
"This has double quotes around it", is that correct?
However, if you use a template, this rule does not apply between your template-specific open and closing tags
that contain Gosu code. Instead, use standard Gosu syntax for the code between those open and closing tags.
In other words, the following two lines are valid Gosu code:
var s = "${ "1" }"
var s = "${ "1" } \"and\" ${ "1" }"
Note that the first character within the template’s Gosu block is an unescaped quote sign.
However, the following is invalid due to improper escaping of internal double quotes:
var s = "${ \"1\" }"
In this invalid case, the first character within the template’s Gosu block is an escaped quote sign.
In the rare case that your Gosu code requires creating a String literal containing a quote character, remember
that the standard Gosu syntax rules apply. This means that you will need to escape any double quote signs that
are within the String literal. For example, the following is valid Gosu:
var quotedString = "${ "\"This has double quotes around it\", is that correct?" }"
Note that the first character within the template’s Gosu block is an unescaped quote sign. This template generates
a String with the value:
"This has double quotes around it", is that correct?
IMPORTANT Be careful with how you escape double quote characters within your embedded Gosu
code or other special template blocks.
• Define template parameters. Template files can define parameters that you pass to the template at run time.
For more information, see “Template Parameters” on page 247.
• Extend a template from a class to simplify static method calls. If
you call static methods on one main class in
your template, you can simplify your template code using the extends feature. For more information, see
“Extending a Template From a Class” on page 248.
To create a new template, add a template file (ending with .gst) in the class hierarchy. Add it within the direc-
tory whose path matches the package in which you want this template to appear. For example, your Gosu
program can have a
The template is a first-class object in the Gosu type system within its package namespace. To run a template, get
a reference to your template and call the renderToString method of the template.
For example, suppose you create a template file NotifyAdminTemplate.gst within the package
mycompany.templates. Your fully-qualified name of the template is
mycompany.templates.NotifyAdminTemplate.
Output to a Writer
The renderToString method outputs the template results to a String value. Optionally, you can render the
template directly to a Java writer object. Your writer must be an instance of java.io.Writer. To output to the
writer, get a reference to the template and call its render method, passing the writer as an argument to the
method.
For example, suppose you create a template file NotifyAdminTemplate.gst within the package
mycompany.templates. If your variable myWriter contains an instance of java.io.Writer, the following Gosu
statement renders the template to the writer:
mycompany.templates.NotifyAdminTemplate.render(myWriter)
If you use template parameters in your template, add your additional parameters after the writer argument. See
“Template Parameters” on page 247 for details.
It is important to note that the result of the scriptlet tag at the beginning of the template does not generate
anything to the output. The value 3 exports to the result because later expression surrounded with the expression
delimiters ${ and } instead of the scriptlet delimiters <% and %>.
The scope of the Gosu continues across scriptlet tags. Use this feature to write advanced logic that uses Gosu
code that you spread across multiple scriptlet tags. For example, the following template code outputs “x is 5” if
the variable x has the value 5, otherwise outputs "x is not 5":
<% if (x == 5) { %>
x is 5
<% } else { %>
x is not 5
<% } %>
Notice that the if statement actually controls the flow of execution of later elements in the template. This feature
allows you to control the export of static text in the template as well as template expressions.
Scriptlet tags are particularly useful when used with template parameters because you can define conditional
logic as shown in the previous example. See “Template Parameters” on page 247 for details.
Use this syntax to iterate across lists, arrays, and other iterable objects. You can combine this syntax with the
expression syntax to generate output from the inner part of your loop. Remember that the scriptlet syntax does
not itself support generating output text.
For example, suppose you set a variable called MyList that contains a List of objects with a Name property. The
following template iterates across the list:
<% for (var obj in MyList) {
var theName = obj.Name %>
Name: ${ theName }
<% } %>
This example also shows a common design pattern for templates that need to combine complex logic in scriptlet
syntax with generated text into the template within a loop:
1. Begin a template scriptlet (starting it with <% ) to begin your loop.
2. Before ending the scriptlet, set up a variable with your data to export
5. Insert a template expression to export your variable, surrounding a Gosu expression with ${ and } tags.
6. Add another template scriptlet (with <% and %>) to contain code that closes your loop. Remember that script-
lets share scope across all scriptlets in that file, so you can reference other variables or close loops or other
Gosu structural elements.
IMPORTANT There is no supported API to generate template output from within a template scriptlet.
Instead, design your template to combine template scriptlets and template expressions using the code
pattern in this topic.
The scriptlet tags are available in template files, but not within String literals using template syntax.
Template Parameters
You can pass parameters of any type to your self-contained Gosu template files.
2. At the top of the template, create a parameter definition with the following syntax:
<%@ params(ARGLIST) %>
In this case, ARGLIST is an argument list just as with a standard Gosu function. For example, the following
argument list includes a String argument and a boolean argument:
<%@ params(x : String, y : boolean) %>
3. Later in the template, use template tags that use the values of those parameters. You can use both the template
expression syntax (${ and }) and template scriptlet syntax (<% and %>). Remember that the expression syntax
always returns a result and generates additional text. In contrast, the scriptlet syntax only executes Gosu state-
ments.
4. To run the template, add your additional parameters to the call to the renderToString method or after the
writer parameter to the render methods.
For example, suppose you create a template file NotifyAdminTemplate.gst within the package
mycompany.templates. Edit the file to contain the following contents:
<%@ params(personName : String, contactHR: boolean) %>
The person ${ personName } must update their contact information in the company directory.
In this example, the if statement (including its trailing curly brace) is within scriptlet tags. The if statement uses
the parameter value at run time to conditionally run elements that appear later in the template. This template
exports the warning to call the human resources department only if the contactHR parameter is true. Use if
statements and other control statements to control the export of static text in the template as well as template
expressions.
Run your template with the following code:
var x : String = mycompany.templates.NotifyAdminTemplate.renderToString("hello", true)
If you want to export to a character writer, use code like the following:
var x : String = mycompany.templates.NotifyAdminTemplate.render(myWriter, "hello", true)
You can use template parameters in template files, but not within String literals that use template syntax.
CLASSNAME must be a fully-qualified class name. You cannot use a package name or hierarchy.
For example, suppose your template wants to clean up the email address with the sanitizeEmailAddress static
method on the class gw.api.email.EmailTemplate. The following template takes one argument that is an email
address:
<%@ params(address : String) %>
<%@ extends gw.api.email.EmailTemplate %>
Hello! The email address is ${sanitizeEmailAddress(address)}
Notice that the class name does not appear immediately before the call to the static method.
You can use the extends syntax in template files, but not within String literals that use template syntax.
Template Comments
You can add comments within your template. Template comments do not affect template output.
The syntax of a template comments is the following:
<%-- your comment here --%>
For example:
My name is <%-- this is a comment --%>John.
You can use template comments in template files, but not within String literals that use template syntax.
Type System
Gosu provides several ways to gather information about an object or other type. This ability for a programming
language to query an object from the outside for this information is referred to as reflection. Use this information
for debugging or to change program behavior based on information gathered at run time.
This topic includes:
• “Basic Type Coercion” on page 251
• “Basic Type Checking” on page 252
• “Using Reflection” on page 256
• “Compound Types” on page 260
• “Type Loaders” on page 261
Syntax
expression as TYPE
The expression must be compatible with the type. The following table lists the results of casting a simple
numeric expression into one of the Gosu-supported data types. If you try to cast an expression to an inappropriate
type, Gosu throws an exception.
Gosu provides automatic downcasting to simplify your code in if statements and similar structures. For more
information, see “Automatic Downcasting for ‘typeis’ and ‘typeof’” on page 254.
For related information, see “Basic Type Checking” on page 252 and “Using Reflection” on page 256.
Typeis Syntax
OBJECT typeis TYPE
Typeis Examples
Expression Result
42 typeis Number true
"auto" typeis String true
person typeis Person true
person typeis Company false
Similarly, you can use the typeof object operator to test against a specific type.
Typeof Syntax
typeof expression
Typeof Examples
Expression Result
typeof 42 Number
typeof "auto" String
typeof (4 + 5) Number
In real-world code, typically you need to check an object against a type or its subtypes, not just a single type. In
such cases, it is better to use typeis instead of typeof. The typeof keyword returns the exact type. If you test
this value with simple equality with another type, it returns false if the object is a subtype.
For example, the following expression returns true:
"hello" typeis Object
In contrast, the following expression returns false because String is a subtype of Object but is a different type:
typeof "hello" == Object
If you want information from the type itself, you can access a type by name (typing its type literal) or use the
typeof operator to get an object’s type. For example:
var s = "hello"
var t = typeof s
In this example, the type of s is String, so the value of the t variable is now String.
The variable is declared as Object. However, at run time it contains an object whose type is String, which is a
subtype of String.
The following example also illustrates how this difference can affect null values and unexpected conditions:
var i : Boolean;
i = null;
print(typeof i)
print(statictypeof i)
At run time, the value of i is null, so its type is void. However, the compile-time type of this variable is
Boolean.
Is Assignable From
For advanced manipulation of type objects, including the method called isAssignableFrom that exists on types,
see “Using Reflection” on page 256.
For advanced manipulation of the Type object, see “Using Reflection” on page 256.
For example, the following example shows a variable declared as an Object, but downcasted to String within
the if statement.
Because of downcasting, the following code is valid:
var x : Object = "nice"
var strlen = 0
It is important to note that length is a property on String, not Object. The downcasting from Object to String
means that you do not need an additional casting around the variable x. In other words, the following code is
equivalent but has an unnecessary cast:
var x : Object = "nice"
var strlen = 0
Do not write Gosu code with unnecessary casts. Use automatic downcasting to write easy-to-read and concise
Gosu code.
The automatic downcasting happens for the following types of statements;
• if statements. For more information, see “If() … Else() Statements” on page 102.
• switch statements. For more information, see “Switch() Statements” on page 105. For example:
uses java.util.Date
This automatic downcasting works when the item to the left of the typeis keyword is a symbol, but not on other
expressions.
There are a several situations that cancel the typeis inference:
• Reaching the end of the extent of the scope for which inference is appropriate. In other words:
• The end of an if statement
• The end of a switch statement
• The end of a ternary conditional expression in its true clause
• Assigning any value to the symbol (the variable) you checked with typeis or typeof. This applies to if and
switch statements.
• An or keyword in a logical expression
• The end of an expression negated with the not keyword
• In a switch statement, a case section does not use automatic downcasting if the previous case section is
unterminated by a break statement. For example, the following Gosu code us valid and both case sections
using automatic downcasting:
uses java.util.Date
Using Reflection
Once you know what type something is, you can use reflection to learn about the type. Although each Type
object itself has properties and methods on it, the most interesting properties and methods are on the
type.TypeInfo object. For example, you can get a type’s complete set of properties and methods at run time by
getting the TypeInfo object.
WARNING In general, avoid using reflection to get properties or call methods. In almost all cases,
you can write Gosu code to avoid reflection. Using reflection dramatically limits how Gosu can alert
you to serious problems at compile time. In general, it is better to detect errors at compile time rather
than unexpected behavior at run time. Only use reflection if there is no other way to do what you need.
The following example shows two different approaches for getting the Name property from a type:
print(Integer.Name) // directly from a Type
print((typeof 29).Name) // getting the Type of something
This prints:
java.lang.Integer
int
for (m in props) {
s = s + m.Name + " "
}
print(s)
You can also call properties using reflection using the square bracket syntax, similar to using arrays. For
example, paste the following code into the Gosu Tester:
// get the CURRENT time
var s = new DateTime()
for (m in methods) {
s = s + m.Name + " "
}
print(s)
This code prints code that looks like this (truncated for clarity):
wait() wait( long, int ) wait( long ) hashCode() getClass() equals( java.lang.Object )
toString() notify() notifyAll() @itype() compareTo( java.lang.String ) charAt( int )
length() subSequence( int, int ) indexOf( java.lang.String, int ) indexOf( java.lang.String )
indexOf( int ) indexOf( int, int ) codePointAt( int ) codePointBefore( int )
You can also get information about individual methods. You can even call methods by name (given a String for
the method name) and pass a list of parameters as object values. You can call a method using the method’s
CallHandler property, which contains a handleCall method.
The following example gets a method by name and then calls it. This example uses the String class and its
compareTo method, which returns 0, 1, or -1. Paste the following code into the Gosu Tester
var mm = String.TypeInfo.Methods
var myMethodName = "compareTo"
// call the method using reflection! ** note: this returns -1 because "a" comes before "b"
print(m.CallHandler.handleCall( obj, { comparisonString } ))
For example, paste the following code into the Gosu Tester:
var s : String = "hello"
var b : Boolean = true
// Using == to compare types is a bad approach if you want to check for valid subtypes...
print("Compare a string to object using == : " + ((typeof s) == Object))
Property Description
Name The human-readable name of this type.
TypeInfo Properties and methods of this type. See “Basic Type Checking” on page 252 for more information
and examples that use this TypeInfo object.
SuperType The supertype of this type, or null if there is no supertype.
IsAbstract If the type is abstract, returns true. See “Modifiers” on page 135.
IsArray If the type is an array, returns true.
IsFinal If the type is final, returns true. See “Modifiers” on page 135.
IsGeneric If the type is generic, returns true. See “Gosu Generics” on page 173.
IsInterface If the type is an interface, returns true. See “Interfaces” on page 147.
IsParameterized If the type is parameterized, returns true. See “Gosu Generics” on page 173.
IsPrimitive If the type is primitive, returns true.
For more information about the isAssignableFrom method on the Type object, refer to the previous section.
type Object, which is the root class of all class instances. For example, collection APIs require all objects to be
of type Object. Thus, collections can contain Integer and Boolean, but not the primitives int or boolean.
However, there are differences while handling uninitialized values, because variables declared of a primitive type
cannot hold the null value, but regular Object variable values can contain null.
For example, paste the following code into the Gosu Tester:
var unboxed : boolean = null // boolean is a primitive type
var boxed : Boolean = null // Boolean is an Object type, a non-primitive
print(unboxed)
print(boxed)
These differences are also notable if you pass primitives to isAssignableFrom. This method only looks at the
type hierarchy and returns false if comparing primitives.
For example, paste the following code into the Gosu Tester:
var unboxed : boolean = true // boolean is a primitive type
var boxed : Boolean = true // Boolean is an Object type, a non-primitive
print((typeof boxed).IsPrimitive)
print((typeof unboxed).IsPrimitive)
print((typeof unboxed).isAssignableFrom( (typeof boxed) ))
In Gosu, the boxed versions of primitives use the Java versions. Because of this, in Gosu you find them defined
in the java.lang package. For example, java.lang.Integer.
For more information about Boolean and boolean, see “Boolean” on page 66.
Compound Types
To implement some other features, Gosu supports a special kind of type called a compound type. A compound
type combines one base class and additional interfaces that the type supports. You can declare a variable to have
a compound type. However, typical usage is only when Gosu automatically creates a variable with a compound
type.
For example, suppose you use the following code to initialize list values:
var x : List<String> = {"a", "b", "c"}
Note: The angle bracket notation indicates support for parameterized types, using Gosu generics features.
For more information, refer to “Gosu Generics” on page 173.
You could also use this syntax using the new operator:
var x = new List<String>(){"a", "b", "c"}
Gosu also supports an extremely compact notation that does not explicitly include the type of the variable:
var x = {"a", "b", "c"}
It might surprise you that this last example is valid Gosu and is typesafe. Gosu infers the type of the List to be
the least upper bound of the components of the list. In the simple case above, the type of the variable x at compile
time is List<String>. If you pass different types of objects, Gosu finds the most specific type that includes all of
the items in the list.
If the types implement interfaces, Gosu attempts to preserve the commonality of interface support in the list type.
This means your list acts as expected with APIs that rely on support for the interface. In some cases, the resulting
type is a compound type, which combines the following into a single type:
• at most one class
• one or more interfaces
For example, the following code initializes an int and a double:
var s = {0, 3.4}
Type Loaders
The Gosu type system has an open type system. An important part of this is that Gosu supports custom type
loaders. A type loader dynamically injects types into the language and attaches potentially complex dynamic
behaviors to working with the type. A custom type loader adds types to the type system and optionally runs
custom code every time any code accesses properties or call methods on them.
There are several built-in type loaders:
• Gosu XML/XSD type loader. This
type loader supports the native Gosu APIs for XML. For more information,
see “Gosu and XML” on page 195.
• Gosu SOAP/WSDL type loader. This type loader supports the native Gosu APIs for the web services SOAP
protocol. This works through a Gosu type loaders that reads web service WSDL files and lets you interact
with the external service through a natural syntax and type-safe coding. For more information, see “Calling
WS-I Web Services from Gosu” on page 225.
This type loader finds property files in the hierarchy of files on the disk along with
• Property file type loader.
your Gosu class files. Gosu creates types in the appropriate package (by the property file location) for each
property. You can access the properties directly in Gosu in a type-safe manner. For more information, see
“Properties Files” on page 277.
You do not need to do anything special to install or enable these type loaders. Gosu includes these type loaders
automatically for all Gosu code.
A future Gosu release will include documentation and supported APIs for creating custom type loaders.
On windows, Gosu uses CMD.EXE to interpret commands. Beware of problems due to limitations of CMD.EXE,
such as a command string may be too long for it. In these cases consider the buildProcess(String) method
instead.
For related tools, see “Helpful APIs for Command Line Gosu Programs” on page 64 in the Gosu Reference
Guide.
Checksums
This topic describes APIs for generating checksums. Longer checksums such as 64-bit checks sums are also
known as fingerprints. Send these fingerprints along with data to improve detection from accidental modification
of data in transit. For example, detecting corrupted stored data or errors in a communication channel.
This topic includes:
• “Overview of Checksums” on page 265
• “Creating Fingerprints” on page 266
• “Extending Fingerprints” on page 267
Overview of Checksums
To improve detection of accidental modification of data in transit, you can use checksums. A checksum is a
computed value generated from an arbitrary block of digital source data. To check the integrity of the data at a
later time, recompute the checksum and compare it with the stored checksum. If the checksums do not match, the
data was almost certainly altered (either intentionally or unintentionally). For example, this technique can help
detection of physical data corruption or errors in a communication channel.
Be aware that checksums cannot perfectly protect against intentional corruption by a malicious agent. A mali-
cious attacker could modify the data so as to preserve its checksum value, or depending on the transport could
substitute a new checksum for the modified data. To guard against malicious changes, use encryption at the data
level (a cryptographic hash) or the transport level (such as SSL/HTTPS).
WARNING Checksums improve detection from accidental modification of data but cannot detect
intentional corruption by a malicious agent. If you need that level of protection, use encryption instead
of checksums, or in addition to checksums.
You can also use fingerprints to design caching and syncing algorithms that check whether data changed since
the last cached copy. You can save the fingerprint of the cached copy and an external system can generate a
fingerprint of its most current data. If you have both fingerprints, compare them to determine if you must resync
the data. To work effectively, the fingerprint algorithm must provide near-certainty that a real-world change
would change the fingerprint. In essence, a fingerprint uniquely identifies the data for most practical purposes,
although in fact collisions (changed data with matching fingerprints) is theoretically possible.
Gosu provides support for 64-bit checksums in the class FP64 in the package gw.util.fingerprint.
The FP64 class provides methods for computing 64-bit fingerprints of the following kinds of data:
• String objects
• character arrays
• byte arrays
• input streams
This implementation is based on an original idea of Michael O. Rabin, with refinements by Andrei Broder.
Fingerprints provide a probabilistic guarantee that defines a mathematical upper bound on the probability of a
collision (a collision occurs if two different strings have the same fingerprint). Using 64-bit fingerprints, the odds
of a collision are extremely small. The odds of a collision between two randomly chosen texts a million charac-
ters long are less than 1 in a trillion.
Suppose you have a set S of n distinct strings each of which is at most m characters long. The odds of any two
different strings in S having the same fingerprint is described by the following equation (k is the number of bits in
the fingerprint):
(nm^2) / 2^k
For practical purposes, you can treat fingerprints as uniquely identifying the bytes that produced them. In mathe-
matical notation given two String variables s1 and s2,using the symbol to mean “implies”:
new FP64(s1).equals(new FP64(s2)) s1.equals(s2)
Do not fingerprint the value of (the raw bytes of) a fingerprint. In other words, do not fingerprint the output of the
FP64 methods toBytes and toHexString. If you do so, due to the shorter length of the fingerprint itself, the prob-
abilistic guarantee is invalid and may lead to unexpected collisions.
Creating Fingerprints
To create a fingerprint object, use the constructor to the FP64 object and pass it one of the supported objects:
An example of passing a String object:
var s = "hello"
var f = new FP64(s)
Note: There is an alternate method signature that takes extra parameters for start position and length of the
desired series of characters in the array.
An example of passing a byte array:
var ba = "hello".Bytes // or use "hello".getBytes(
var f = new FP64(ba)
Note: There is an alternate method signature that takes extra parameters for start position and length of the
desired series of byes in the array.
An example of passing a stream:
var s = "testInputStreamConstructor"
new FP64(new ByteArrayInputStream(gw.util.StreamUtil.toBytes(s))));
An example of passing another FP64 fingerprint object to the constructor to duplicate the fingerprint:
var s = "hello"
var f = new FP64(s)
var f2 = new FP64(f)
Extending Fingerprints
This class also provides methods for extending an existing fingerprint by more bytes or characters. This is useful
if you are sure the only change to the source data was appending a known series of bytes to the end of the orig-
inal String data.
Extending the fingerprint of one String by another String produces a fingerprint equivalent to the fingerprint of
the concatenation of the two String objects. Given the two String variables s1 and s2, this means the following
is true:
new FP64(s1 + s2).equals( new FP64(s1).extend(s2) )
All operations for extending a fingerprint are destructive. In other words, they modify the fingerprint object
directly (in-place). All operations return the resulting FP64 object, so you can chain method calls together, such
as the following:
new FP64("x").extend(foo).extend(92))
If you want to make a copy of a fingerprint, use the FP64 constructor and pass the FP64 object to copy:
var original = new FP64("Hello world")
var copy = new FP64(original) // a duplicate of the original fingerprint
Concurrency
This topic describes Gosu APIs that protect shared data from access from multiple threads.
This topic includes:
• “Overview of Thread Safety and Concurrency” on page 269
• “Gosu Scoping Classes (Pre-scoped Maps)” on page 270
• “Concurrent Lazy Variables” on page 271
• “Concurrent Cache” on page 272
• “Concurrency with Monitor Locks and Reentrant Objects” on page 273
There are other special cases in which you must be particularly careful. For example, if you want to manage a
single local memory cache that applies to multiple threads, you must carefully synchronize all reads and writes to
shared data.
WARNING Static variables can be extremely dangerous in a multi-threaded environment. Using static
variables in a multi-threaded environment can cause problems in a production deployment if you do
not properly synchronize access. If such problems occur, they are extremely difficult to diagnose and
debug. Timing in an multi-user multi-threaded environment is difficult, if not impossible, to control in
a testing environment.
Gosu provides the following types of concurrency APIs to make it easy for you to write thread-safe code:
• Scoping classes (pre-scoped maps). Scope-related utilities in the class gw.api.web.Scopes help synchronize
and protect access to shared data. These APIs return Map objects into which you can get and put data using
different scope semantics. Gosu automatically synchronizes the Map objects to provide proper concurrent
access semantics. For more information, see “Gosu Scoping Classes (Pre-scoped Maps)” on page 270
• Lazy concurrent variables. The LazyVar class (in gw.util.concurrent) implements what some people call a
lazy variable. This means Gosu constructs it only the first time some code uses it. Because the LazyVar class
uses the Java concurrency libraries, access to the lazy variable is thread-safe. The LazyVar class wraps the
double-checked locking pattern in a typesafe holder. For more information, see “Concurrent Lazy Variables”
on page 271
• Concurrent cache. The Cache class (in gw.util.concurrent) declares a cache of values you can look up
quickly and in a thread-safe way. It declares a concurrent cache similar to a Least Recently Used (LRU)
cache. Because the Cache class uses the Java concurrency libraries, access to the concurrent cache is thread-
safe. For more information, see “Concurrent Cache” on page 272.
WARNING Caches are difficult to implement and use. Caches can cause subtle problems. Use caches
only as a last result for performance. If you use a cache, it is best to request multiple people on your
team carefully review cache-related code.
• Support for Java monitor locks, reentrant locks, and custom reentrant objects. Gosu provides access to Java-
based classes for monitor locks and reentrant locks in the Java package java.util.concurrent. Gosu makes
it easier to access these classes with easy-to-read using clauses that also properly handle cleanup if excep-
tions occur. Additionally, Gosu makes it easy to create custom Gosu objects that support an easy-to-read
syntax for reentrant object handling. For more information, see “Concurrency with Monitor Locks and Reen-
trant Objects” on page 273.
IMPORTANT These methods are available only in execution contexts that are associated with a web
request. If you attempt to accessed these methods in other contexts, Gosu throws an
IllegalStateException exception. Be aware that how this data is stored is dependent on the applica-
tion server container in which your application runs. Your data must satisfy any constraints that
container imposes. For example, some application containers might require that your objects are serial-
izable (implement the Serializable interface).
Request A single thread-local request. getRequest Returns a Map to store and retrieve values whose lifes-
scope pan is the lifespan of the request. This map is not syn-
chronized since multiple threads typically cannot get to
the same request object. You could create unexpected
situations by passing this object to other threads, so
you must avoid such actions.
Session One web session getSession Returns a Map to store and retrieve values whose lifes-
pan is the lifespan of the users session. This map is
automatically synchronized since multiple threads can
access the session simultaneously. For example, web
AJAX requests.
Applica- The entire Gosu application, getApplication Returns a Map to store and retrieve values whose lifes-
tion including all requests and sub- pan is the lifespan of the web application. This is almost
threads. identical to static variables, but Gosu clears the map if a
servlet shuts down and is later restarted.
// lazy variable using a block that calls a resource-intensive operation that retuns a String
static var _data : java.util.Map
construct() {
// set variable in our scoped object. The object ensures any access is thread-safe.
_data["Name"] = "John Smith"
}
}
As you can see, the parameter is a block that creates a new object. In this case, it returns a new ArrayList. You
can create any object. In real world cases this block might be very resource-intensive to create (or load) this
object.
It is best to let Gosu infer the proper type of the block type or the result of the make method, as shown in this
example. This simplifies your code so that you do not need to use explicit Gosu generics syntax to define the type
of the block itself, such as the following verbose version:
var _lazy : LazyVar<List<String>> = LazyVar.make( \-> new ArrayList<String>() )
var i = _lazy.get()
If the Gosu has not yet run the block, it does when you access it. If Gosu has run the block, it simply returns the
cached value and does not rerun the block.
A good approach to using lazy variables is to define it as a static variable and then define a property accessor
function to abstract away the implementation of the variable. The following is an example inside a Gosu class
definition:
class MyClass {
// lazy variable using a block that calls a resource-intensive operation that retuns a String
var _lazy = LazyVar.make( \-> veryExpensiveMethodThatRetunsAString() )
If any code accesses the property MyLazyString, Gosu calls its property accessor function. The property accessor
always calls the get method on the object. However, Gosu only runs the very expensive method once, the first
time someone accesses the lazy variable value. If any code accesses this property again, the cached value is used.
Gosu does not execute the block again. This is useful in cases where you want some system to come up quickly
and only pay incremental costs for resource-intensive value calculations.
Concurrent Cache
A similar class to the LazyVar class is the Cache class. It declares a cache of values you can look up quickly and
in a thread-safe way. It declares a concurrent cache similar to a Least Recently Used (LRU) cache. Because the
Cache class uses the Java concurrency libraries, access to the cache is thread-safe.
2. Use the key and value types to parameterize the Cache type using Gosu generics syntax. For example, if you
want to pass a String and get an Integer back from the cache, create a new Cache<String, Integer>.
3. In the constructor, pass the following arguments:
• a name for your cache as a String - the implementation uses this name to generate logging for cache
misses
• the size of your cache, as a number of slots
• a block that defines a function that calculates a value from an input value. Presumably this is a resource-
intensive calculation.
For example,
// A cache of string values to their upper case values
var myCache = new Cache<String, String>( "My Uppercase Cache", 100, \ s -> s.toUpperCase() )
4. To use the cache, just call the get method and pass the input value (the key). If the value is in the cache, it
simply returns it from the cache. If it is not cached, Gosu calls the block and calculates it from the input value
(the key) and then caches the result. For example:
print(myCache.get("Hello world")
print(myCache.get("Hello world")
This prints:
"HELLO WORLD"
"HELLO WORLD"
In this example, the first time you call the get method, it calls the block to generate the upper case value. The
second time you call the get method, the value is the same but Gosu uses the cached value. Any times you
call the get method later, the value is the same but Gosu uses the cached value, assuming it still in the cache.
If too many items were added to the cache and your desired item is unavailable, Gosu reruns the block to
regenerate the value. Gosu then caches the result.
Alternatively, if you want to use a cache within some other class, you can define a static instance of the cache.
The static variable definition itself defines your block. Again, because the Cache class uses the Java concurrency
libraries, it is thread-safe. For example, in your class definition, define a static variable like this:
static var _upperCaseCache = new Cache<Foo, Bar>( 1000, \ foo -> getBar( foo ) )
To use your cache, your class can get a value from the cache using code like the following. In this example,
inputString is a String variable that may or may not contain a String that you used before with this cache:
var fastValue = _upperCaseCache.get( inputString )
The first time you call the get method, it calls the block to generate the upper case value.
Any later times you call the get method, the value is the same but Gosu uses the cached value, assuming it still in
the cache. If too many items were added to the cache and your desired item is unavailable, Gosu reruns the block
to regenerate the value. Gosu then caches the result in the concurrent cache object.
An even better way to use the cache is to abstract the cache implementation into a property accessor function. Let
the private static object Cache object (as shown in the previous example) handle the actual cache. For example,
define a property accessor function such as:
static property get function UpperCaseQuickly( str : String ) {
return _upperCaseCache.get( str )
}
These are demonstrations only with a simple and non-resource-intensive operation in the block. Generally
speaking, it is only worth the overhead of maintaining the cache if your calculation is resource-intensive
combined with potentially repeated access with the same input values.
WARNING Caching can be difficult and error prone in complex applications. It can lead to run time
errors and data corruption if you do not do it carefully. Only use caches as a last resort for performance
issues. Because of the complexity of cache code, always have multiple experienced programmers
review any cache-related code.
// a property get function uses the lock and calls another method for the main work
property get SomeProp() : Object
using( _lock ) {
return _someVar.someMethod() // do your main work here and Gosu synchronizes it
}
...
The using statement automatically cleans up the lock, even if there code throws exceptions.
In contrast, this is a traditionally-structured verbose use of a lock using try and finally statements:
uses java.util.concurrent
...
...
Note: Although this approach is possible, returning the value from a block imposes some more restrictions
on how you implement your return statements. Instead, it is usually better to use the using statement struc-
ture at the beginning of this topic.
The using statement version works with these lock objects because Gosu considers this objects reentrant.
Re-entrant objects are objects that help manage safe access to data that is shared by re-entrant or concurrent code
execution. For example, if you must store data that is shared by multiple threads, ensure that you protect against
concurrent access from multiple threads to prevent data corruption. The most prominent type of shared data is
class static variables, which are variables that are stored on the Gosu class itself.
For Gosu to recognize a valid reentrant object, the object must have one of the following attributes:
• Implements the java.util.concurrent.locks.Lock interface. This includes the Java classes in that
pacakge: ReentrantLock, ReadWriteLock, Condition.
• Casted to the Gosu interface IMonitorLock. You can cast any arbitrary object to IMonitorLock. This is
useful to cast Java monitor locks to this Gosu interface. For more information about monitor locks, refer to:
http://en.wikipedia.org/wiki/Monitor_(synchronization)
• Implements the Gosu class gw.lang.IReentrant. This interface contains two methods with no arguments:
enter and exit. Your code must properly lock or synchronize data access as appropriate during the enter
method and release any locks in the exit method.
For blocks of code using locks (code that implements java.util.concurrent.locks.Lock), a using clause
simplifies your code.
The following code uses the java.util.concurrent.locks.ReentrantLock class using a longer (non-recom-
mended) form:
// in your class variable definitions...
var _lock : ReentrantLock = new ReentrantLock()
function useReentrantLockOld() {
_lock.lock()
try {
// do your main work here
}
finally {
_lock.unlock()
}
}
In contrast, you can write more readable Gosu code using the using keyword:
function useReentrantLockNew() {
using( _lock ) {
// do your main work here
}
}
Similarly, you can cast any object to a monitor lock by adding “as IMonitorLock” after the object. For example,
the following method call code uses itself (using the special keyword this) as the monitor lock:
function monitorLock() {
using( this as IMonitorLock ) {
// do stuff
}
}
For example:
using( var out = new FileOutputStream( this, false ) ) {
out.write( content )
}
You can combine the multiple item feature with the ability to assign variables. For more about assigning vari-
ables, see “Assigning Variables Inside ‘using’ Expression Declaration” on page 275 .
For example:
using( var lfc = new FileInputStream(this).Channel,
var rfc = new FileInputStream(that).Channel ) {
lbuff.clear()
rbuff.clear()
}
return false
}
}
Gosu ensures that all objects are properly cleaned up. In other words, for each object to create or resource to
acquire, if it creates or acquires successfully, Gosu releases, closes, or disposes the object. Also note that if one of
the resources fails to create, Gosu does not attempt to acquire other resources in later-appearing items in the
command-seperated list. Instead, Gosu simply releases the ones that did succeed.
For more information about using clauses, see “Object Lifecycle Management (‘using’ Clauses)” on page 122 in
the Gosu Reference Guide.
Note: For more information about concurrency and related APIs in Java, see:
http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html
Properties Files
Gosu includes automatic support for reading properties files in the Java properties format.
This topic includes:
• “Reading Properties Files” on page 277
2. Decide where in your package hierarchy that you want to reference your properties file. For example, suppose
the root of your class hierarchy is the path /MyProject/gsrc. If you want your properties file to be in the
package com.mycompany.config and the properties file to be called MyProps.properties, create a new file at
the path:
/MyProject/gsrc/com/mycompany/config/MyProps.properties
website = http://gosu-lang.org/
language = English
message = Welcome to \
Gosu!
# Unicode support
tab : \u0009
print("accessing properties...")
print("")
To test this code with a Gosu program instead of a Gosu class, create a Gosu program called PropsTest.gsp one
level higher than the root of your class hierarchy. Add a classpath statement to add the root of the class hier-
archy to the class path. See “Setting the Class Path to Call Other Gosu or Java Classes” on page 60.
Although it is a legal Java property, Gosu does not provide programmatic access to it.
Coding Style
This topic lists some recommended coding practices for the Gosu language. These guidelines encourage good
programming practices that improve Gosu readability and encourage code that is error-free, easy to understand,
and easy to maintain by other people.
This topic includes:
• “General Coding Guidelines” on page 279
Type Declarations
Omit the type declaration if you declare variables with an assignment. Instead, use “as TYPE” where appropriate.
The type declaration is particularly redundant if a value needs coerce to a type already included at the end of the
Gosu statement.
In other words, the recommended type declaration style is:
var delplans = currentPage as DelinquencyPlans
Use these operators where possible instead of using the equals method on objects. This protection with null is
called null-safety.
Notice that Gosu’s == operator is equivalent to the object method equals (obj1.equals(obj2)) other than its
difference in null-safety.
Note: For those who use the Java language also, the null-safety of the Gosu == operator is similar to the
null-safety of the Java code ObjectUtil.equals(...). In contrast, for both the Gosu and Java languages,
the object method myobject.equals(...) is not null-safe.
So, any Gosu code that use the equals method, such as:
( planName.equals( row.Name.text ) )
Although the == and the != comparison operators are more powerful and more convenient than equals(), be
aware of coercions that may occur. For example, because expressions adhere to Gosu’s implicit coercion rules,
the expression 1 == "1" evaluates to true. In other words, the number 1 and the string representing the number
1 is true. This is because of implicit coercion that allows the string "1" to be assigned to an integer variable as the
integer 1 without explicit casting.
While coercion behavior is convenient and powerful, it can be dangerous if used carelessly. Gosu produces
compile warnings for implicit coercions. Take the warnings seriously and in most cases explicitly cast using the
as keyword in cases that you want the coercion. Otherwise, fix the problem by rewriting in some other way
entirely.
For example, an expression equates a date value with a string representation of a date value:
(dateVal == strVal)
Carefully consider any implicit direct coercions that might occur with the == operator, and explicitly define coer-
cions where possible.
If comparing array equality with the == and != operators, Gosu does not let you compare incompatible array
types. For example, the following code generates a compile time error because arrays of numbers and strings are
incompatible:
new Number[] {1,2} == new String[] {"1","2"}
However, if the array types are comparable, Gosu recursively applies implicit coercion rules on the
array’s elements. For example, the following code evaluates to true because a Number is a subclass of Object,
so the Gosu compares the individual elements of the table:
new Number[] {1,2} == new Object[] {"1","2"}
WARNING Be careful if comparing arrays. Note the recursive comparison of individual elements for
compatible array types.
For more information about the difference between == and === operators in Gosu, see “=== Operator Compares
Object Equality” on page 83
• method names
• property names
• package names
• all other language elements.
In addition to the performance inmprovement, using proper capitalization makes your code easier to read.
For more examples and additional information on this topic, see “Gosu Case Sensitivity” on page 33.
This declares a private variable called _firstname, which Gosu exposes as a public property called FirstName.
Do not do this:
public var FirstName : String // do not do this. Public variable scope is not Gosu standard style
For more information about defining properties, see “Properties” on page 130.
IMPORTANT For Gosu classes data fields, the standard Gosu style is to use public properties backed
by private variables rather than public variables. Do not use public variables in new Gosu classes. See
“Properties” on page 130 for more information.
For example, the following example shows a variable declared as an Object, but downcasted to String within
the if statement in a block of code within an if statement.
Because of downcasting, the following code is valid:
var x : Object = "nice"
var strlen = 0
This works because the typeis inference is effective immediately and propagates to adjacent expressions.
It is important to note that length is a property on String, not Object. The downcasting from Object to String
means that you do not need an additional casting around the variable x. In other words, the following code is
equivalent but has an unnecessary cast:
var x : Object = "nice"
var strlen = 0
Use automatic downcasting to write easy-to-read and concise Gosu code. Do not write Gosu code with unneces-
sary casts. For more information, see “Automatic Downcasting for ‘typeis’ and ‘typeof’” on page 254 in the
Gosu Reference Guide.