Elan Language Reference

# Named values

In most programming, the term variable describes a data entity in a program that contains a value and has a name by which you can read and write its value, i.e. its value can be varied. In Elan, these data entities are called named values so that a distinction can be made between:

- mutable named values whose content can be assigned and reassigned, e.g. defined with a variable definition instruction and reassigned with a change variable instruction or, for standard data structures, there are methods for their update.
- immutable named values whose content is assigned, e.g. with a constant instruction, or a let instruction in a function, and then cannot be reassigned. There are, however, methods for copying an immutable named value into another (or even the same) named value with specified changes.

This distinction applies both to single values and to data structures (which contain multiple values) and, while it is most pertinent in Functional Programming, it provides a useful discipline in any code. Preferring immutable named values can help avoid duplication, assist in the modularisation of code and reduce errors.

Both kinds of named value must be initialised with literals, expressions or initialisation methods. The counter variable in a for loop, however, may be used without having been initialised.

## Data Types

There are two fundamentally different kinds of data Type, differing by how their values are passed around in a running program:

- Value Types that contain a single value, and are passed around directly:
  `IntintintIntegerint`, `FloatfloatdoubleDoubledouble`, `BooleanboolboolBooleanbool`
- Reference Types that contain a more complex structure of values, and are passed around by references to them:
  `StringstrstringStringString`, `ListlistListListList`, etc. as well as any user-defined Type such as the name of a concrete class, abstract class or interface.

This table lists the value Types and the standard data structure (reference) Types, each linking to its definition and further details:

Type group | Value Types | Reference Types
--- | --- | ---
Value data | Integer `IntintintIntegerint`  | Floating point (Real) number `FloatfloatdoubleDoubledouble`  | Truth value `BooleanboolboolBooleanbool`  |  |  |  |
Standard data structures |  |  |  | Character string `StringstrstringStringString`  | Regular expression `RegExpRegExpRegExpRegExpRegExp`  | List `ListlistListListList`  | Look-up dictionary `DictionaryDictionaryDictionaryDictionaryDictionary` 
Set `HashSetHashSetHashSetHashSetHashSet`  | LIFO stack `StackStackStackStackStack`  | FIFO queue `QueueQueueQueueQueueQueue`  |
Graphics |  |  |  | Turtle graphics `TurtleTurtleTurtleTurtleTurtle`  | SVG vector graphics `LineVGLineVGLineVGLineVGLineVG` `RectangleVGRectangleVGRectangleVGRectangleVGRectangleVG` `CircleVGCircleVGCircleVGCircleVGCircleVG` `ImageVGImageVGImageVGImageVGImageVG` `RawVGRawVGRawVGRawVGRawVG`  | Block graphics (2D array) `List<of List<of Int>>list[list[int]]List<List<int>>List(Of List(Of Integer))List<List<int>>`  |
Data I/O |  |  |  | Text file output `TextFileWriterTextFileWriterTextFileWriterTextFileWriterTextFileWriter`  | Text file input `TextFileReaderTextFileReaderTextFileReaderTextFileReaderTextFileReader`  |  |
User-defined |  |  |  | Enumeration `enumenumenumenumenum`  | Concrete class `classclassclassclassclass`  | Abstract class abstract `classclassclassclassclass`  | Interface `interfaceinterfaceinterfaceinterfaceinterface` 
Other |  |  |  | Random number `RandomRandomRandomRandomRandom`  | Argument reference `AsRefAsRefAsRefAsRefAsRef`  | Optional property `MaybeMaybeMaybeMaybeMaybe`  |

Named values are statically typed: their Type, once defined, cannot be changed. A named value's Type is:

- either automatically inferred from the value of the literal or expression defining a value Type,
- or specified in the definition of:
  - data structures whose items have a particular Type, e.g. `List<of Int>list[int]List<int>List(Of Integer)List<int>`
  - parameters of functions and procedures
  - return value of a function
  - property of an interface, abstract class or concrete class

## Mutability of named values

The properties or contents of a named value that is of an immutable Type may not be changed directly. You can, however, create another instance that is a copy of the original with all the same property values except for specific changes that you want to make. The newly-minted copy (with changes) may be assigned either to a new named value, or as a re-definition of the original named value.

This table shows which named values can be reassigned and/or mutated depending on how they were defined:

define named value | named value | notes
--- | --- | ---
with | as mutable Type | as immutable Type | reassign with reassign | mutate | scope
constant  | ✘ | ✔ | ✘ | ✘ | global | values are assigned only at compile time
variable definition  | ✔ | ✔ | ✔ | ✔ | local | values are assigned during execution
parameter (by value)  | ✔ | ✘ | ✘ | ✔ | local | formal input argument of function, procedure or lambda
parameter (by reference)  | ✔ | ✘ | ✘ | ✘ | local | formal input and output argument of function, procedure or lambda

## Identifiers and Type names

### Named value identifier

The name given to every named value must follow the rules for an identifier:

- It must start with either a lowercase letter or an underscore, followed by any combination ot letters (upper- or lowercase), digits and underscore symbols.
- It must not contain spaces or symbols other than underscore.
- It cannot be the same as any language keyword, method or other reserved word. If you happen to choose such a name, an error message will tell you that it cannot be used for an identifier.
- Like all the language's keywords, it is case-sensitive.
- You cannot use two identifiers within the same scope that differ only in case, e.g. `varxvarxvarxvarxvarx` and `varXvarXvarXvarXvarX`.

### Type name

Every Type, whether system (e.g. `ListlistListListList`) or user-defined (e.g. `classclassclassclassclass` MyClass), is named like an identifier but with one important difference: its first character must be an uppercase letter. Type names are also case-sensitive.

## Scope and name qualification

'Scope' in the table above refers to where in your code a named value is accessible. Global constants  and enums , being the only values having global scope, can be referenced from anywhere in your program. Every other kind of named value is local and restricted to the procedure or function within which it is defined.

Local named values can have the same name as a global constant, function, or procedure (which are all defined at global level or are in the standard library). In such cases, when the name is used within the same method, then it will refer to the local definition.

## Dot syntax

Reference to a named value is in many cases made with dot syntax, also referred to as applying a dot method. Here are its uses:

- To apply a function method to a named value, e.g. to obtain the length of String s using a library method:
  `variable nname? set to s.length()value or expression?0nname? = s.length()value or expression? # variable definition0var nname? = s.length()value or expression?;0Dim nname? = s.length()value or expression? ' variable definition0var nname? = s.length()value or expression?;0`
- To apply a procedure to a named value, e.g. to initialise `ListlistListListList` li using a library procedure:
  `call li.initialiseprocedureName?(10, 0arguments?)0li.initialiseprocedureName?(10, 0arguments?) # call procedure0li.initialiseprocedureName?(10, 0arguments?); // call procedure0li.initialiseprocedureName?(10, 0arguments?) ' call procedure0li.initialiseprocedureName?(10, 0arguments?); // call procedure0`
- To refer to the property (body) of an instance (g) of class Game and, in this example, to get the length of the property's current string value, using library methods:
  `variable bodyGLname? set to g.body.toString().length()value or expression?0bodyGLname? = g.body.toString().length()value or expression? # variable definition0var bodyGLname? = g.body.toString().length()value or expression?;0Dim bodyGLname? = g.body.toString().length()value or expression? ' variable definition0var bodyGLname? = g.body.toString().length()value or expression?;0`
- To extract an item from a Tuple using its special properties item_N, e.g. to get the first value from a 2-Tuple:
  `variable pointname? set to (3, 7)value or expression?0pointname? = (3, 7)value or expression? # variable definition0var pointname? = (3, 7)value or expression?;0Dim pointname? = (3, 7)value or expression? ' variable definition0var pointname? = (3, 7)value or expression?;0`
  `variable xname? set to point.item_0value or expression?0xname? = point.item_0value or expression? # variable definition0var xname? = point.item_0value or expression?;0Dim xname? = point.item_0value or expression? ' variable definition0var xname? = point.item_0value or expression?;0`
- To refer to a 'value' in an enum, e.g.to pick one of the identifiers in the enum `SuitSuitSuitSuitSuit`:
  `enum SuitName? spades, hearts, diamonds, clubsvalues?values?1class SuitName?(Enum):
  spades = 1
  hearts = 2
  diamonds = 3
  clubs = 4values?1enum SuitName? {spades, hearts, diamonds, clubsvalues?values?}1Enum SuitName?
  spades = 0
  hearts = 1
  diamonds = 2
  clubs = 3
  End Enumvalues?1enum SuitName? {spades, hearts, diamonds, clubsvalues?values?}1`
  `variable suitname? set to Suit.spadesvalue or expression?0suitname? = Suit.spadesvalue or expression? # variable definition0var suitname? = Suit.spadesvalue or expression?;0Dim suitname? = Suit.spadesvalue or expression? ' variable definition0var suitname? = Suit.spadesvalue or expression?;0`

You cannot use dot syntax with functions and procedures that you define at the global level, nor with some system functions (e.g. abs) and procedures (e.g. clearPrintedText).

# Global instructions

Global instructions (also referred to as globals) are located directly in your code at the highest level. They are never indented from the left-hand edge, nor may they be located within other instructions. They are: main , procedure , function , test , concrete class , abstract class , interface , constant  and enum .

- main, procedure and function are described as methods and these are defined by one or more statement instructions  within them.
- test also contains instructions, in particular the assert equal  instruction for testing functions during development of your program.
- concrete class, abstract class, and interface define data structures and these always contain members .
- constant and enum do not contain any further instructions: only names and values.
- The sequence of global instructions in your code is immaterial, with two exceptions:
  - If one constant is used in the definition of another constant, the first must be declared above the second.
  - An abstract class must be declared above any concrete class that inherits from it.

## main

A program must have a main method, sometimes called its main routine, if it is intended to be run as a program. You may, however, develop and test code that does not have a main method, either as a coding exercise or for subsequent use within another program.

The main method defines the start point of a program when it is run (executed).

It does not have to be at the top of the file, but this is a good convention to follow.

It may delegate work to one or more procedures  or functions .

There may not be more than one main in a program file, and the Global prompt will not show main as an option when one already exists in the file.

#### Example of a main method

● A main method

+main 1 variable li name? set to [3, 6, 1, 0, 99, 4, 67]value or expression?2 call inPlaceRippleSort procedureName?(li arguments?)3 call print procedureName?(li arguments?)4 end main
+def main() -> None: 1 li name? = [3, 6, 1, 0, 99, 4, 67]value or expression? # variable definition 2 inPlaceRippleSort procedureName?(li arguments?) # call procedure 3 print procedureName?(li arguments?)4 main()
+static void main() { 1 var li name? = [3, 6, 1, 0, 99, 4, 67]value or expression?;2 inPlaceRippleSort procedureName?(li arguments?); // call procedure 3 print procedureName?(li arguments?);4 } // main
+Sub main() 1 Dim li name? = {3, 6, 1, 0, 99, 4, 67}value or expression? ' variable definition 2 inPlaceRippleSort procedureName?(li arguments?) ' call procedure 3 print procedureName?(li arguments?)4 End Sub
+static void main() { 1 var li name? = [3, 6, 1, 0, 99, 4, 67]value or expression?;2 inPlaceRippleSort procedureName?(li arguments?); // call procedure 3 print procedureName?(li arguments?);4 } // main

## procedure

A procedure is a named piece of code that may have parameters that are given inputs via arguments in a call procedure  instruction.

Its name must follow the rules for an identifier .

Unlike a function:

- a procedure can have side effects: indeed it should have side effects, otherwise there would be no point in calling it.
- a procedure does not return a value.
- a procedure's parameter named values (that are mutable) may be changed inside the procedure, but they do not affect the value of arguments in the call procedure instruction outside the procedure.
- to pass a changed parameter back to its calling argument, it must have been called by reference .

The instructions within a procedure can therefore:

- include calls to other procedures, or to itself if recursion  is required.
- include data input methods and other system functions such as for random number generation.

Procedure calls are of two kinds:

- to execute an action:
  `call printprocedureName?(aListarguments?)0printprocedureName?(aListarguments?)0printprocedureName?(aListarguments?);0printprocedureName?(aListarguments?)0printprocedureName?(aListarguments?);0`
- to apply a procedure to a value using dot syntax :
  `call aList.removeAtprocedureName?(4arguments?)0aList.removeAtprocedureName?(4arguments?) # call procedure0aList.removeAtprocedureName?(4arguments?); // call procedure0aList.removeAtprocedureName?(4arguments?) ' call procedure0aList.removeAtprocedureName?(4arguments?); // call procedure0`

These calls are to library procedures, but the same options are applicable to the procedures you write.

#### Example of a procedure

● Procedure to order a list of integers:

+procedure inPlaceRippleSort name?(li as List<of Int>parameter definitions?) 1 variable hasChanged name? set to true value or expression?2 variable lastComp name? set to li.length() - 2 value or expression?3 +while hasChanged is true condition? 4 reassign hasChanged variableName? to false value or expression?5 +for i item? in range(0, lastComp + 1)source? 6 +if li[i] > li[i + 1]condition? then 7 variable temp name? set to li[i]value or expression?8 reassign li[i]variableName? to li[i + 1]value or expression?9 reassign li[i + 1]variableName? to temp value or expression?10 reassign hasChanged variableName? to true value or expression?11 end if end for reassign lastComp variableName? to lastComp - 1 value or expression?12 end while end procedure
+def inPlaceRippleSort name?(li: list[int]parameter definitions?) -> None: # procedure 1 hasChanged name? = True value or expression? # variable definition 2 lastComp name? = li.length() - 2 value or expression? # variable definition 3 +while hasChanged == True condition?: 4 hasChanged variableName? = False value or expression? # reassign variable 5 +for i item? in range(0, lastComp + 1)source?: 6 +if li[i] > li[i + 1]condition?: 7 temp name? = li[i]value or expression? # variable definition 8 li[i]variableName? = li[i + 1]value or expression? # reassign variable 9 li[i + 1]variableName? = temp value or expression? # reassign variable 10 hasChanged variableName? = True value or expression? # reassign variable 11 lastComp variableName? = lastComp - 1 value or expression? # reassign variable 12
+static void inPlaceRippleSort name?(List<int> li parameter definitions?) { // procedure 1 var hasChanged name? = true value or expression?;2 var lastComp name? = li.length() - 2 value or expression?;3 +while (hasChanged == true condition?) { 4 hasChanged variableName? = false value or expression?; // reassign variable 5 +foreach (i item? in range(0, lastComp + 1)source?) { 6 +if (li[i] > li[i + 1]condition?) { 7 var temp name? = li[i]value or expression?;8 li[i]variableName? = li[i + 1]value or expression?; // reassign variable 9 li[i + 1]variableName? = temp value or expression?; // reassign variable 10 hasChanged variableName? = true value or expression?; // reassign variable 11 } // if } // foreach lastComp variableName? = lastComp - 1 value or expression?; // reassign variable 12 } // while } // procedure
+Sub inPlaceRippleSort name?(li As List(Of Integer)parameter definitions?) ' procedure 1 Dim hasChanged name? = True value or expression? ' variable definition 2 Dim lastComp name? = li.length() - 2 value or expression? ' variable definition 3 +While hasChanged = True condition? 4 hasChanged variableName? = False value or expression? ' reassign variable 5 +For Each i item? In range(0, lastComp + 1)source? 6 +If li[i] > li[i + 1]condition? Then 7 Dim temp name? = li[i]value or expression? ' variable definition 8 li[i]variableName? = li[i + 1]value or expression? ' reassign variable 9 li[i + 1]variableName? = temp value or expression? ' reassign variable 10 hasChanged variableName? = True value or expression? ' reassign variable 11 End If Next i lastComp variableName? = lastComp - 1 value or expression? ' reassign variable 12 End While End Sub
+static void inPlaceRippleSort name?(List<int> li parameter definitions?) { // procedure 1 var hasChanged name? = true value or expression?;2 var lastComp name? = li.length() - 2 value or expression?;3 +while (hasChanged == true condition?) { 4 hasChanged variableName? = false value or expression?; // reassign variable 5 +foreach (i item? in range(0, lastComp + 1)source?) { 6 +if (li[i] > li[i + 1]condition?) { 7 var temp name? = li[i]value or expression?;8 li[i]variableName? = li[i + 1]value or expression?; // reassign variable 9 li[i + 1]variableName? = temp value or expression?; // reassign variable 10 hasChanged variableName? = true value or expression?; // reassign variable 11 } // if } // foreach lastComp variableName? = lastComp - 1 value or expression?; // reassign variable 12 } // while } // procedure

### Call by reference

To change the value in named value arg supplied as an argument in a procedure call, both the call argument and the procedure parameter must use a reference (or pointer) to it, defined as Type `AsRefAsRefAsRefAsRefAsRef`. This then allows use of the dot methods value and set on it to read and change its value, as in this example:

#### Example of a call by reference

● argRef is a pointer to variable arg in main, so that arg can be accessed elsewhere by reference:

+main 1 variable arg name? set to "abc"value or expression?2 variable argRef name? set to new AsRef<of String>(arg)value or expression?3 call changeArg procedureName?(argRef arguments?)4 call print procedureName?(argRef.value()arguments?)5 end main +procedure changeArg name?(pointer as AsRef<of String>parameter definitions?) 6 variable r name? set to pointer.value()value or expression?7 call pointer.set procedureName?(r.upperCase()arguments?)8 end procedure
+def main() -> None: 1 arg name? = "abc"value or expression? # variable definition 2 argRef name? = AsRef[str](arg)value or expression? # variable definition 3 changeArg procedureName?(argRef arguments?) # call procedure 4 print procedureName?(argRef.value()arguments?)5 +def changeArg name?(pointer: AsRef[str]parameter definitions?) -> None: # procedure 6 r name? = pointer.value()value or expression? # variable definition 7 pointer.set procedureName?(r.upperCase()arguments?) # call procedure 8 main()
+static void main() { 1 var arg name? = "abc"value or expression?;2 var argRef name? = new AsRef<string>(arg)value or expression?;3 changeArg procedureName?(argRef arguments?); // call procedure 4 print procedureName?(argRef.value()arguments?);5 } // main +static void changeArg name?(AsRef<string> pointer parameter definitions?) { // procedure 6 var r name? = pointer.value()value or expression?;7 pointer.set procedureName?(r.upperCase()arguments?); // call procedure 8 } // procedure
+Sub main() 1 Dim arg name? = "abc"value or expression? ' variable definition 2 Dim argRef name? = New AsRef(Of String)(arg)value or expression? ' variable definition 3 changeArg procedureName?(argRef arguments?) ' call procedure 4 print procedureName?(argRef.value()arguments?)5 End Sub +Sub changeArg name?(pointer As AsRef(Of String)parameter definitions?) ' procedure 6 Dim r name? = pointer.value()value or expression? ' variable definition 7 pointer.set procedureName?(r.upperCase()arguments?) ' call procedure 8 End Sub
+static void main() { 1 var arg name? = "abc"value or expression?;2 var argRef name? = new AsRef<String>(arg)value or expression?;3 changeArg procedureName?(argRef arguments?); // call procedure 4 print procedureName?(argRef.value()arguments?);5 } // main +static void changeArg name?(AsRef<String> pointer parameter definitions?) { // procedure 6 var r name? = pointer.value()value or expression?;7 pointer.set procedureName?(r.upperCase()arguments?); // call procedure 8 } // procedure

## function

A function is a named piece of code that can define parameters which are given inputs via arguments when reference to the function occurs in an instruction or expression. Its name must follow the rules for an identifier .

Unlike a procedure :

- a function always returns a value.
- a function can have no side effects (i.e. no references outside its code) and cannot depend on any System methods .
- a function's execution cannot be interrupted by any external event, though a a non-terminating loop in a function may be detected with tests that time out .

A function definition is comprised of its unique name and, in brackets, its input parameters with their Types, followed by `returnsreturnsreturnsreturnsreturns`, and the Type of the value that will be returned.

A return instruction is automatically added as the last instruction of a function (since a function must return a value), and there can be only one return instruction in a function. You follow the return instruction with the value to be returned by the function. This may be an expression that will be evaluated before returning.

#### Examples of functions

● Function to search a list of strings:

+function binarySearch name?(li as List<of String>, item as String parameter definitions?) returns Boolean Type? 1 variable result name? set to false value or expression?2 +if li.length() > 0 condition? then 3 variable mid name? set to divAsInt(li.length(), 2)value or expression?4 variable value name? set to li[mid]value or expression?5 +if item.equals(value)condition? then 6 reassign result variableName? to true value or expression?7 elif item.isBefore(value)condition? then 8 reassign result variableName? to binarySearch(li.subList(0, mid), item)value or expression?9 else 10 reassign result variableName? to binarySearch(li.subList(mid + 1, li.length()), item)value or expression?11 end if end if return result value or expression?12 end function
+def binarySearch name?(li: list[str], item: str parameter definitions?) -> bool Type?: # function 1 result name? = False value or expression? # variable definition 2 +if li.length() > 0 condition?: 3 mid name? = divAsInt(li.length(), 2)value or expression? # variable definition 4 value name? = li[mid]value or expression? # variable definition 5 +if item.equals(value)condition?: 6 result variableName? = True value or expression? # reassign variable 7 elif item.isBefore(value)condition?: # else if 8 result variableName? = binarySearch(li.subList(0, mid), item)value or expression? # reassign variable 9 else:10 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression? # reassign variable 11 return result value or expression?12
+static bool Type? binarySearch name?(List<string> li, string item parameter definitions?) { // function 1 var result name? = false value or expression?;2 +if (li.length() > 0 condition?) { 3 var mid name? = divAsInt(li.length(), 2)value or expression?;4 var value name? = li[mid]value or expression?;5 +if (item.equals(value)condition?) { 6 result variableName? = true value or expression?; // reassign variable 7 } else if (item.isBefore(value)condition?) {8 result variableName? = binarySearch(li.subList(0, mid), item)value or expression?; // reassign variable 9 } else {10 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression?; // reassign variable 11 } // if } // if return result value or expression?;12 } // function
+Function binarySearch name?(li As List(Of String), item As String parameter definitions?) As Boolean Type? 1 Dim result name? = False value or expression? ' variable definition 2 +If li.length() > 0 condition? Then 3 Dim mid name? = divAsInt(li.length(), 2)value or expression? ' variable definition 4 Dim value name? = li[mid]value or expression? ' variable definition 5 +If item.equals(value)condition? Then 6 result variableName? = True value or expression? ' reassign variable 7 ElseIf item.isBefore(value)condition? Then 8 result variableName? = binarySearch(li.subList(0, mid), item)value or expression? ' reassign variable 9 Else 10 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression? ' reassign variable 11 End If End If Return result value or expression?12 End Function
+static bool Type? binarySearch name?(List<String> li, String item parameter definitions?) { // function 1 var result name? = false value or expression?;2 +if (li.length() > 0 condition?) { 3 var mid name? = divAsInt(li.length(), 2)value or expression?;4 var value name? = li[mid]value or expression?;5 +if (item.equals(value)condition?) { 6 result variableName? = true value or expression?; // reassign variable 7 } else if (item.isBefore(value)condition?) {8 result variableName? = binarySearch(li.subList(0, mid), item)value or expression?; // reassign variable 9 } else {10 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression?; // reassign variable 11 } // if } // if return result value or expression?;12 } // function

● A function definition and reference to it:

+function score name?(g as Game parameter definitions?) returns Int Type? 1 return g.body.length() - 2 value or expression?2 end function +main 3 variable g name? set to new Game()value or expression?4 call print procedureName?(score(g)arguments?)5 end main
+def score name?(g: Game parameter definitions?) -> int Type?: # function 1 return g.body.length() - 2 value or expression?2 +def main() -> None: 3 g name? = Game()value or expression? # variable definition 4 print procedureName?(score(g)arguments?)5 main()
+static int Type? score name?(Game g parameter definitions?) { // function 1 return g.body.length() - 2 value or expression?;2 } // function +static void main() { 3 var g name? = new Game()value or expression?;4 print procedureName?(score(g)arguments?);5 } // main
+Function score name?(g As Game parameter definitions?) As Integer Type? 1 Return g.body.length() - 2 value or expression?2 End Function +Sub main() 3 Dim g name? = New Game()value or expression? ' variable definition 4 print procedureName?(score(g)arguments?)5 End Sub
+static int Type? score name?(Game g parameter definitions?) { // function 1 return g.body.length() - 2 value or expression?;2 } // function +static void main() { 3 var g name? = new Game()value or expression?;4 print procedureName?(score(g)arguments?);5 } // main

### Recursion

Procedures and functions may be called or referenced recursively, as in this simple factorial calculation:

+function factorial name?(n as Int parameter definitions?) returns Int Type? 1 return (if(n > 1, n*factorial(n - 1), 1))value or expression?2 end function
+def factorial name?(n: int parameter definitions?) -> int Type?: # function 1 return (if(n > 1, n*factorial(n - 1), 1))value or expression?2
+static int Type? factorial name?(int n parameter definitions?) { // function 1 return (if(n > 1, n*factorial(n - 1), 1))value or expression?;2 } // function
+Function factorial name?(n As Integer parameter definitions?) As Integer Type? 1 Return (if(n > 1, n*factorial(n - 1), 1))value or expression?2 End Function
+static int Type? factorial name?(int n parameter definitions?) { // function 1 return (if(n > 1, n*factorial(n - 1), 1))value or expression?;2 } // function

## test

A test instruction is at the global level, and consists of a set of assertions about the outputs of functions.

Without having to run your program, the assert equal instructions show whether your assertions pass or fail.

#### Example of a set of assert equal instructions that test a function

● Test function binarySearch on four test lists

+test test_binarySearch test_name? 1 variable li1 name? set to ["lemon", "lime", "orange"]value or expression?2 assert binarySearch(li1, "lemon")actual (computed) value? is true expected value? not run 3 assert binarySearch(li1, "lime")actual (computed) value? is true expected value? not run 4 assert binarySearch(li1, "orange")actual (computed) value? is true expected value? not run 5 assert binarySearch(li1, "pear")actual (computed) value? is false expected value? not run 6 variable li2 name? set to ["lemon", "orange"]value or expression?7 assert binarySearch(li2, "lemon")actual (computed) value? is true expected value? not run 8 assert binarySearch(li2, "orange")actual (computed) value? is true expected value? not run 9 assert binarySearch(li2, "pear")actual (computed) value? is false expected value? not run 10 variable li3 name? set to ["lemon"]value or expression?11 assert binarySearch(li3, "lemon")actual (computed) value? is true expected value? not run 12 assert binarySearch(li3, "lime")actual (computed) value? is false expected value? not run 13 variable li4 name? set to new List<of String>()value or expression?14 assert binarySearch(li4, "pear")actual (computed) value? is false expected value? not run 15 end test
+def test_binarySearch test_name?(self) -> None: 1 li1 name? = ["lemon", "lime", "orange"]value or expression? # variable definition 2 self.assertEqual(binarySearch(li1, "lemon")actual (computed) value?, True expected value?) not run 3 self.assertEqual(binarySearch(li1, "lime")actual (computed) value?, True expected value?) not run 4 self.assertEqual(binarySearch(li1, "orange")actual (computed) value?, True expected value?) not run 5 self.assertEqual(binarySearch(li1, "pear")actual (computed) value?, False expected value?) not run 6 li2 name? = ["lemon", "orange"]value or expression? # variable definition 7 self.assertEqual(binarySearch(li2, "lemon")actual (computed) value?, True expected value?) not run 8 self.assertEqual(binarySearch(li2, "orange")actual (computed) value?, True expected value?) not run 9 self.assertEqual(binarySearch(li2, "pear")actual (computed) value?, False expected value?) not run 10 li3 name? = ["lemon"]value or expression? # variable definition 11 self.assertEqual(binarySearch(li3, "lemon")actual (computed) value?, True expected value?) not run 12 self.assertEqual(binarySearch(li3, "lime")actual (computed) value?, False expected value?) not run 13 li4 name? = list[str]()value or expression? # variable definition 14 self.assertEqual(binarySearch(li4, "pear")actual (computed) value?, False expected value?) not run 15
+[TestMethod] static void test_binarySearch test_name?() { 1 var li1 name? = ["lemon", "lime", "orange"]value or expression?;2 Assert.AreEqual(true expected value?, binarySearch(li1, "lemon")actual (computed) value?) not run 3 Assert.AreEqual(true expected value?, binarySearch(li1, "lime")actual (computed) value?) not run 4 Assert.AreEqual(true expected value?, binarySearch(li1, "orange")actual (computed) value?) not run 5 Assert.AreEqual(false expected value?, binarySearch(li1, "pear")actual (computed) value?) not run 6 var li2 name? = ["lemon", "orange"]value or expression?;7 Assert.AreEqual(true expected value?, binarySearch(li2, "lemon")actual (computed) value?) not run 8 Assert.AreEqual(true expected value?, binarySearch(li2, "orange")actual (computed) value?) not run 9 Assert.AreEqual(false expected value?, binarySearch(li2, "pear")actual (computed) value?) not run 10 var li3 name? = ["lemon"]value or expression?;11 Assert.AreEqual(true expected value?, binarySearch(li3, "lemon")actual (computed) value?) not run 12 Assert.AreEqual(false expected value?, binarySearch(li3, "lime")actual (computed) value?) not run 13 var li4 name? = new List<string>()value or expression?;14 Assert.AreEqual(false expected value?, binarySearch(li4, "pear")actual (computed) value?) not run 15 } // test
+<TestMethod> Sub test_binarySearch test_name?() 1 Dim li1 name? = {"lemon", "lime", "orange"}value or expression? ' variable definition 2 Assert.AreEqual(True expected value?, binarySearch(li1, "lemon")actual (computed) value?) not run 3 Assert.AreEqual(True expected value?, binarySearch(li1, "lime")actual (computed) value?) not run 4 Assert.AreEqual(True expected value?, binarySearch(li1, "orange")actual (computed) value?) not run 5 Assert.AreEqual(False expected value?, binarySearch(li1, "pear")actual (computed) value?) not run 6 Dim li2 name? = {"lemon", "orange"}value or expression? ' variable definition 7 Assert.AreEqual(True expected value?, binarySearch(li2, "lemon")actual (computed) value?) not run 8 Assert.AreEqual(True expected value?, binarySearch(li2, "orange")actual (computed) value?) not run 9 Assert.AreEqual(False expected value?, binarySearch(li2, "pear")actual (computed) value?) not run 10 Dim li3 name? = {"lemon"}value or expression? ' variable definition 11 Assert.AreEqual(True expected value?, binarySearch(li3, "lemon")actual (computed) value?) not run 12 Assert.AreEqual(False expected value?, binarySearch(li3, "lime")actual (computed) value?) not run 13 Dim li4 name? = New List(Of String)()value or expression? ' variable definition 14 Assert.AreEqual(False expected value?, binarySearch(li4, "pear")actual (computed) value?) not run 15 End Sub
+@Test static void test_binarySearch test_name?() { 1 var li1 name? = ["lemon", "lime", "orange"]value or expression?;2 assertEquals(true expected value?, binarySearch(li1, "lemon")actual (computed) value?) not run 3 assertEquals(true expected value?, binarySearch(li1, "lime")actual (computed) value?) not run 4 assertEquals(true expected value?, binarySearch(li1, "orange")actual (computed) value?) not run 5 assertEquals(false expected value?, binarySearch(li1, "pear")actual (computed) value?) not run 6 var li2 name? = ["lemon", "orange"]value or expression?;7 assertEquals(true expected value?, binarySearch(li2, "lemon")actual (computed) value?) not run 8 assertEquals(true expected value?, binarySearch(li2, "orange")actual (computed) value?) not run 9 assertEquals(false expected value?, binarySearch(li2, "pear")actual (computed) value?) not run 10 var li3 name? = ["lemon"]value or expression?;11 assertEquals(true expected value?, binarySearch(li3, "lemon")actual (computed) value?) not run 12 assertEquals(false expected value?, binarySearch(li3, "lime")actual (computed) value?) not run 13 var li4 name? = new List<String>()value or expression?;14 assertEquals(false expected value?, binarySearch(li4, "pear")actual (computed) value?) not run 15 } // test

#### Notes

- Elan tests are designed to test functions only. It is not possible to call a procedure or main routine within a test. Nor is it possible to use any System method  (the same rule as for a function).
- A test may optionally be given a name or description in free-form text, just like a comment, which plays no role in the execution of the test. You might give the test the same name as a function that it is testing, or you might describe a particular scenario that is being tested.
- test instructions may be written anywhere in the code, provided they are at the global level.
- A test instruction may contain any number of assert equal instructions. The test runner is part of the IDE and it automatically attempts to run all assert equal instructions showing each one's pass or fail outcome alongside. However, if the test hits a runtime error (as distinct from an assert equal failure) then execution of the test will stop and remaining assert equals will be shown as 'not run'.
- In addition to assert equal instructions, a test may contain any other instructions that may be added into a function.
- All assert equal statements should be at the top level within the test instruction; none may be put into a loop structure.

### Testing `FloatfloatdoubleDoubledouble` values

When testing `FloatfloatdoubleDoubledouble` values it is recommend that you use the round method to round the computed result to a fixed number of decimal places. This avoids rounding errors and is easier to read. For example:

+test test_round test_name? 1 assert sqrt(2).round(3)actual (computed) value? is 1.414 expected value? not run 2 end test
+def test_round test_name?(self) -> None: 1 self.assertEqual(sqrt(2).round(3)actual (computed) value?, 1.414 expected value?) not run 2
+[TestMethod] static void test_round test_name?() { 1 Assert.AreEqual(1.414 expected value?, sqrt(2).round(3)actual (computed) value?) not run 2 } // test
+<TestMethod> Sub test_round test_name?() 1 Assert.AreEqual(1.414 expected value?, sqrt(2).round(3)actual (computed) value?) not run 2 End Sub
+@Test static void test_round test_name?() { 1 assertEquals(1.414 expected value?, sqrt(2).round(3)actual (computed) value?) not run 2 } // test

### Testing for runtime errors

If the expression you are testing would cause a runtime error then the error will be displayed in the red fail message:

If there are failures, mark the tests that you added since the last successful test as `ghostedghostedghostedghostedghosted`  and then remove their ghosted status one by one until the cause is identified and fixed.

+test test_list test_name? 1 variable a name? set to [5, 1, 7]value or expression?2 assert a[0]actual (computed) value? is 5 expected value? not run 3 assert a[2]actual (computed) value? is 7 expected value? not run 4 end test
+def test_list test_name?(self) -> None: 1 a name? = [5, 1, 7]value or expression? # variable definition 2 self.assertEqual(a[0]actual (computed) value?, 5 expected value?) not run 3 self.assertEqual(a[2]actual (computed) value?, 7 expected value?) not run 4
+[TestMethod] static void test_list test_name?() { 1 var a name? = [5, 1, 7]value or expression?;2 Assert.AreEqual(5 expected value?, a[0]actual (computed) value?) not run 3 Assert.AreEqual(7 expected value?, a[2]actual (computed) value?) not run 4 } // test
+<TestMethod> Sub test_list test_name?() 1 Dim a name? = {5, 1, 7}value or expression? ' variable definition 2 Assert.AreEqual(5 expected value?, a[0]actual (computed) value?) not run 3 Assert.AreEqual(7 expected value?, a[2]actual (computed) value?) not run 4 End Sub
+@Test static void test_list test_name?() { 1 var a name? = [5, 1, 7]value or expression?;2 assertEquals(5 expected value?, a[0]actual (computed) value?) not run 3 assertEquals(7 expected value?, a[2]actual (computed) value?) not run 4 } // test

This assert shows how testing can also be done against an expected error message:

+test test_message test_name? 1 variable a name? set to [5, 1, 7]value or expression?2 assert a[4]actual (computed) value? is 0 expected value? not run 3 assert a[4]actual (computed) value? is "Out of range index: 4 size: 3"expected value? not run 4 end test
+def test_message test_name?(self) -> None: 1 a name? = [5, 1, 7]value or expression? # variable definition 2 self.assertEqual(a[4]actual (computed) value?, 0 expected value?) not run 3 self.assertEqual(a[4]actual (computed) value?, "Out of range index: 4 size: 3"expected value?) not run 4
+[TestMethod] static void test_message test_name?() { 1 var a name? = [5, 1, 7]value or expression?;2 Assert.AreEqual(0 expected value?, a[4]actual (computed) value?) not run 3 Assert.AreEqual("Out of range index: 4 size: 3"expected value?, a[4]actual (computed) value?) not run 4 } // test
+<TestMethod> Sub test_message test_name?() 1 Dim a name? = {5, 1, 7}value or expression? ' variable definition 2 Assert.AreEqual(0 expected value?, a[4]actual (computed) value?) not run 3 Assert.AreEqual("Out of range index: 4 size: 3"expected value?, a[4]actual (computed) value?) not run 4 End Sub
+@Test static void test_message test_name?() { 1 var a name? = [5, 1, 7]value or expression?;2 assertEquals(0 expected value?, a[4]actual (computed) value?) not run 3 assertEquals("Out of range index: 4 size: 3"expected value?, a[4]actual (computed) value?) not run 4 } // test

### Testing long strings

If you have a test that compares strings longer than 20 characters, any test failure message will be reduced to reporting the first character at which the actual (computed) and expected strings differ.

#### Example of testing long strings

● Reporting the first character at which the actual (computed) and expected strings differ:

+constant sGW name? set to "grid { display: flex; flex-direction: column; margin-top: 40px; width: 500px; } word { display: flex; flex-direction: row; margin: auto; }"literal value or data structure?1 +function setInStyle name?(s as String parameter definitions?) returns String Type? 2 return "<style>" + s + "<style>"value or expression?3 end function +test test_setInStyle test_name? 4 assert setInStyle(sGW)actual (computed) value? is "<style>" + sGW + "<style>"expected value? not run 5 # assert fail message will be "s found at [146] {expected: /)"comment? end test
+sGW name? = "grid { display: flex; flex-direction: column; margin-top: 40px; width: 500px; } word { display: flex; flex-direction: row; margin: auto; }"literal value or data structure? # constant 1 +def setInStyle name?(s: str parameter definitions?) -> str Type?: # function 2 return "<style>" + s + "<style>"value or expression?3 +def test_setInStyle test_name?(self) -> None: 4 self.assertEqual(setInStyle(sGW)actual (computed) value?, "<style>" + sGW + "<style>"expected value?) not run 5 # assert fail message will be "s found at [146] {expected: /)"comment?
+const String sGW name? = "grid { display: flex; flex-direction: column; margin-top: 40px; width: 500px; } word { display: flex; flex-direction: row; margin: auto; }"literal value or data structure?1 +static string Type? setInStyle name?(string s parameter definitions?) { // function 2 return "<style>" + s + "<style>"value or expression?;3 } // function +[TestMethod] static void test_setInStyle test_name?() { 4 Assert.AreEqual("<style>" + sGW + "<style>"expected value?, setInStyle(sGW)actual (computed) value?) not run 5 // assert fail message will be "s found at [146] {expected: /)"comment? } // test
+Const sGW name? = "grid { display: flex; flex-direction: column; margin-top: 40px; width: 500px; } word { display: flex; flex-direction: row; margin: auto; }"literal value or data structure?1 +Function setInStyle name?(s As String parameter definitions?) As String Type? 2 Return "<style>" + s + "<style>"value or expression?3 End Function +<TestMethod> Sub test_setInStyle test_name?() 4 Assert.AreEqual("<style>" + sGW + "<style>"expected value?, setInStyle(sGW)actual (computed) value?) not run 5 ' assert fail message will be "s found at [146] {expected: /)"comment? End Sub
+final String sGW name? = "grid { display: flex; flex-direction: column; margin-top: 40px; width: 500px; } word { display: flex; flex-direction: row; margin: auto; }"literal value or data structure? // constant 1 +static String Type? setInStyle name?(String s parameter definitions?) { // function 2 return "<style>" + s + "<style>"value or expression?;3 } // function +@Test static void test_setInStyle test_name?() { 4 assertEquals("<style>" + sGW + "<style>"expected value?, setInStyle(sGW)actual (computed) value?) not run 5 // assert fail message will be "s found at [146] {expected: /)"comment? } // test

### Ignoring tests

To ignore tests, use `ghostingghostingghostingghostingghosting` .

Even when tests or assert equals are `ghostedghostedghostedghostedghosted`, all the tests will be run and their status shown, but the overall test status will show the status of only the unghosted tests (green pass, amber warning or red fail).

#### Examples of ghosting tests

● Ghosting an entire test:

+test test_overApple test_name? variable g1 name? set to new Game(new Random())value or expression? variable g2 name? set to g1.withApple(new Square(23, 15))value or expression? assert headOverApple(g2)actual (computed) value? is false expected value? not run variable g3 name? set to g2.withHead(new Square(23, 15))value or expression? assert headOverApple(g3)actual (computed) value? is true expected value? not run end test
+def test_overApple test_name?(self) -> None: g1 name? = Game(Random())value or expression? # variable definition g2 name? = g1.withApple(Square(23, 15))value or expression? # variable definition self.assertEqual(headOverApple(g2)actual (computed) value?, False expected value?) not run g3 name? = g2.withHead(Square(23, 15))value or expression? # variable definition self.assertEqual(headOverApple(g3)actual (computed) value?, True expected value?) not run
+[TestMethod] static void test_overApple test_name?() { var g1 name? = new Game(new Random())value or expression?; var g2 name? = g1.withApple(new Square(23, 15))value or expression?; Assert.AreEqual(false expected value?, headOverApple(g2)actual (computed) value?) not run var g3 name? = g2.withHead(new Square(23, 15))value or expression?; Assert.AreEqual(true expected value?, headOverApple(g3)actual (computed) value?) not run } // test
+<TestMethod> Sub test_overApple test_name?() Dim g1 name? = New Game(New Random())value or expression? ' variable definition Dim g2 name? = g1.withApple(New Square(23, 15))value or expression? ' variable definition Assert.AreEqual(False expected value?, headOverApple(g2)actual (computed) value?) not run Dim g3 name? = g2.withHead(New Square(23, 15))value or expression? ' variable definition Assert.AreEqual(True expected value?, headOverApple(g3)actual (computed) value?) not run End Sub
+@Test static void test_overApple test_name?() { var g1 name? = new Game(new Random())value or expression?; var g2 name? = g1.withApple(new Square(23, 15))value or expression?; assertEquals(false expected value?, headOverApple(g2)actual (computed) value?) not run var g3 name? = g2.withHead(new Square(23, 15))value or expression?; assertEquals(true expected value?, headOverApple(g3)actual (computed) value?) not run } // test

● Ghosting an assert:

+test test_overApple test_name? 1 variable g1 name? set to new Game(new Random())value or expression?2 variable g2 name? set to g1.withApple(new Square(23, 15))value or expression?3 assert headOverApple(g2)actual (computed) value? is true expected value? not run variable g3 name? set to g2.withHead(new Square(23, 15))value or expression?4 assert headOverApple(g3)actual (computed) value? is true expected value? not run 5 end test
+def test_overApple test_name?(self) -> None: 1 g1 name? = Game(Random())value or expression? # variable definition 2 g2 name? = g1.withApple(Square(23, 15))value or expression? # variable definition 3 self.assertEqual(headOverApple(g2)actual (computed) value?, True expected value?) not run g3 name? = g2.withHead(Square(23, 15))value or expression? # variable definition 4 self.assertEqual(headOverApple(g3)actual (computed) value?, True expected value?) not run 5
+[TestMethod] static void test_overApple test_name?() { 1 var g1 name? = new Game(new Random())value or expression?;2 var g2 name? = g1.withApple(new Square(23, 15))value or expression?;3 Assert.AreEqual(true expected value?, headOverApple(g2)actual (computed) value?) not run var g3 name? = g2.withHead(new Square(23, 15))value or expression?;4 Assert.AreEqual(true expected value?, headOverApple(g3)actual (computed) value?) not run 5 } // test
+<TestMethod> Sub test_overApple test_name?() 1 Dim g1 name? = New Game(New Random())value or expression? ' variable definition 2 Dim g2 name? = g1.withApple(New Square(23, 15))value or expression? ' variable definition 3 Assert.AreEqual(True expected value?, headOverApple(g2)actual (computed) value?) not run Dim g3 name? = g2.withHead(New Square(23, 15))value or expression? ' variable definition 4 Assert.AreEqual(True expected value?, headOverApple(g3)actual (computed) value?) not run 5 End Sub
+@Test static void test_overApple test_name?() { 1 var g1 name? = new Game(new Random())value or expression?;2 var g2 name? = g1.withApple(new Square(23, 15))value or expression?;3 assertEquals(true expected value?, headOverApple(g2)actual (computed) value?) not run var g3 name? = g2.withHead(new Square(23, 15))value or expression?;4 assertEquals(true expected value?, headOverApple(g3)actual (computed) value?) not run 5 } // test

### Non-terminating loops and recursion

The principal reason for ghosting a test is when either the test code, or code in any function being called, does not terminate. This typically means that there is a loop (or a recursive call) with no exit condition, or where the exit condition is never met.

If you do create such code without realising it, then when the tests are executed the test runner will time out after a few seconds (most tests will pass in milliseconds), and an error message will appear. Your priority should then be to identify the cause of the timeout and attempt to fix it before then unghosting the `testtesttesttesttest`.

## concrete class

A concrete class is a user-defined Type offering richer capability than an enum .

Like any other Type its name must begin with an uppercase letter.

### Defining a concrete class

A concrete class is instantiated using the concrete class instruction followed by the class name, and optional inherits to refer to a menu option class or abstract class defined above in the program.

A class definition must include properties, a constructor and at least one method called toString.

Its properties must all be initialised in the constructor.

It may contain functions and procedure methods.

The constructor may optionally define parameters to force the calling code to provide initial values.

Code in the constructor may make use of any functions, and follows the same constraints as a function (i.e. it may not call any procedure, whether defined in the class or outside).

A simple demonstration of a concrete class is:

+main 1 variable x name? set to new Thing()value or expression?2 call print procedureName?(x arguments?)3 call print procedureName?(x.names.toString()arguments?)4 end main +class Thing Name? inheritance?5 property names name? as List<of String>Type?6 +constructor(parameter definitions parameter definitions?) 7 reassign this.names variableName? to createList(6, "X")value or expression?8 end constructor +function toString name?(parameter definitions parameter definitions?) returns String Type? 9 return "instance of class Thing"value or expression?10 end function end class
+def main() -> None: 1 x name? = Thing()value or expression? # variable definition 2 print procedureName?(x arguments?)3 print procedureName?(x.names.toString()arguments?)4 +class Thing Name? inheritance? # concrete class 5 names name?: list[str]Type? # property 6 +def __init__(self: Thing) -> None: 7 self.names variableName? = createList(6, "X")value or expression? # reassign variable 8 +def toString name?(self: Thing) -> str Type?: # function method 9 return "instance of class Thing"value or expression?10 main()
+static void main() { 1 var x name? = new Thing()value or expression?;2 print procedureName?(x arguments?);3 print procedureName?(x.names.toString()arguments?);4 } // main +class Thing Name? inheritance? {5 public List<string>Type? names name? {get; private set;} // property 6 +public Thing(parameter definitions parameter definitions?) { 7 this.names variableName? = createList(6, "X")value or expression?; // reassign variable 8 } // constructor +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 9 return "instance of class Thing"value or expression?;10 } // function method } // class
+Sub main() 1 Dim x name? = New Thing()value or expression? ' variable definition 2 print procedureName?(x arguments?)3 print procedureName?(x.names.toString()arguments?)4 End Sub +Class Thing Name? inheritance? inheritance?5 Property names name? As List(Of String)Type?6 +Sub New(parameter definitions parameter definitions?) 7 Me.names variableName? = createList(6, "X")value or expression? ' reassign variable 8 End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 9 Return "instance of class Thing"value or expression?10 End Function End Class
+static void main() { 1 var x name? = new Thing()value or expression?;2 print procedureName?(x arguments?);3 print procedureName?(x.names.toString()arguments?);4 } // main +class Thing Name? inheritance? inheritance? {5 public List<String>Type? names name?; // property 6 +public Thing(parameter definitions parameter definitions?) { 7 this.names variableName? = createList(6, "X")value or expression?; // reassign variable 8 } // constructor +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 9 return "instance of class Thing"value or expression?;10 } // function method } // class

Here is an example of concrete class definition taken from demo program snake - object-oriented:

#### Example definition of a concrete class

● Apple:

+class Apple Name? inheritance?1 +constructor(parameter definitions parameter definitions?) 2 reassign this.location variableName? to new Square(0, 0)value or expression?3 end constructor +function toString name?(parameter definitions parameter definitions?) returns String Type? 4 return ""value or expression?5 end function property location name? as Square Type?6 +procedure newRandomPosition name?(snake as Snake parameter definitions?) 7 variable changePosition name? set to true value or expression?8 +while changePosition condition? 9 variable ranX name? set to randint(0, 39)value or expression?10 variable ranY name? set to randint(0, 29)value or expression?11 reassign this.location variableName? to new Square(ranX, ranY)value or expression?12 +if not snake.bodyCovers(this.location)condition? then 13 reassign changePosition variableName? to false value or expression?14 end if end while end procedure +procedure updateBlocks name?(blocks as List<of List<of Int>>parameter definitions?) 15 reassign blocks[this.location.x][this.location.y]variableName? to red value or expression?16 end procedure end class
+class Apple Name? inheritance? # concrete class 1 +def __init__(self: Apple) -> None: 2 self.location variableName? = Square(0, 0)value or expression? # reassign variable 3 +def toString name?(self: Apple) -> str Type?: # function method 4 return ""value or expression?5 location name?: Square Type? # property 6 +def newRandomPosition name?(self: Apple, snake: Snake parameter definitions?) -> None: # procedure method 7 changePosition name? = True value or expression? # variable definition 8 +while changePosition condition?: 9 ranX name? = randint(0, 39)value or expression? # variable definition 10 ranY name? = randint(0, 29)value or expression? # variable definition 11 self.location variableName? = Square(ranX, ranY)value or expression? # reassign variable 12 +if not snake.bodyCovers(self.location)condition?: 13 changePosition variableName? = False value or expression? # reassign variable 14 +def updateBlocks name?(self: Apple, blocks: list[list[int]]parameter definitions?) -> None: # procedure method 15 blocks[self.location.x][self.location.y]variableName? = red value or expression? # reassign variable 16
+class Apple Name? inheritance? {1 +public Apple(parameter definitions parameter definitions?) { 2 this.location variableName? = new Square(0, 0)value or expression?; // reassign variable 3 } // constructor +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 4 return ""value or expression?;5 } // function method public Square Type? location name? {get; private set;} // property 6 +public void newRandomPosition name?(Snake snake parameter definitions?) { // procedure method 7 var changePosition name? = true value or expression?;8 +while (changePosition condition?) { 9 var ranX name? = randint(0, 39)value or expression?;10 var ranY name? = randint(0, 29)value or expression?;11 this.location variableName? = new Square(ranX, ranY)value or expression?; // reassign variable 12 +if (!snake.bodyCovers(this.location)condition?) { 13 changePosition variableName? = false value or expression?; // reassign variable 14 } // if } // while } // procedure method +public void updateBlocks name?(List<List<int>> blocks parameter definitions?) { // procedure method 15 blocks[this.location.x][this.location.y]variableName? = red value or expression?; // reassign variable 16 } // procedure method } // class
+Class Apple Name? inheritance? inheritance?1 +Sub New(parameter definitions parameter definitions?) 2 Me.location variableName? = New Square(0, 0)value or expression? ' reassign variable 3 End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 4 Return ""value or expression?5 End Function Property location name? As Square Type?6 +Sub newRandomPosition name?(snake As Snake parameter definitions?) ' procedure method 7 Dim changePosition name? = True value or expression? ' variable definition 8 +While changePosition condition? 9 Dim ranX name? = randint(0, 39)value or expression? ' variable definition 10 Dim ranY name? = randint(0, 29)value or expression? ' variable definition 11 Me.location variableName? = New Square(ranX, ranY)value or expression? ' reassign variable 12 +If Not snake.bodyCovers(Me.location)condition? Then 13 changePosition variableName? = False value or expression? ' reassign variable 14 End If End While End Sub +Sub updateBlocks name?(blocks As List(Of List(Of Integer))parameter definitions?) ' procedure method 15 blocks[Me.location.x][Me.location.y]variableName? = red value or expression? ' reassign variable 16 End Sub End Class
+class Apple Name? inheritance? inheritance? {1 +public Apple(parameter definitions parameter definitions?) { 2 this.location variableName? = new Square(0, 0)value or expression?; // reassign variable 3 } // constructor +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 4 return ""value or expression?;5 } // function method public Square Type? location name?; // property 6 +public void newRandomPosition name?(Snake snake parameter definitions?) { // procedure method 7 var changePosition name? = true value or expression?;8 +while (changePosition condition?) { 9 var ranX name? = randint(0, 39)value or expression?;10 var ranY name? = randint(0, 29)value or expression?;11 this.location variableName? = new Square(ranX, ranY)value or expression?; // reassign variable 12 +if (!snake.bodyCovers(this.location)condition?) { 13 changePosition variableName? = false value or expression?; // reassign variable 14 } // if } // while } // procedure method +public void updateBlocks name?(List<List<int>> blocks parameter definitions?) { // procedure method 15 blocks[this.location.x][this.location.y]variableName? = red value or expression?; // reassign variable 16 } // procedure method } // class

### this

If in the code of `classclassclassclassclass` A you want to invoke a method in `classclassclassclassclass` S and pass to it the current instance of A, you can refer to this instance with `thisthisthisthisthis`, as shown by this line in demo program Snake - object-oriented:

`call apple.newRandomPositionprocedureName?(thisarguments?)0apple.newRandomPositionprocedureName?(selfarguments?) # call procedure0apple.newRandomPositionprocedureName?(thisarguments?); // call procedure0apple.newRandomPositionprocedureName?(Mearguments?) ' call procedure0apple.newRandomPositionprocedureName?(thisarguments?); // call procedure0`

Here, method newRandomPosition is defined on class `AppleAppleAppleAppleApple` which needs to be passed an instance of class `SnakeSnakeSnakeSnakeSnake`, apple being an instance of class `AppleAppleAppleAppleApple`.

### inherits

A concrete class  (often referred to simply as a class) may optionally inherit from just one abstract class A  but may additionally inherit from any number of interfaces . The concrete class must define for itself a concrete implementation of every abstract member defined in the abstract class or any interface(s) that it inherits from, directly or indirectly.

#### Notes

- An abstract class must be declared in the code above any class that inherits from it.
- The abstract class (if any) and the interfaces (if any) that a concrete class inherits from may not contain duplicates of any abstract member. Any duplicated definitions in the hierarchy will result in a compile error. If such duplications arise, you should factor out the common member definitions, and move them up the hierarchy or into new interfaces inherited by the interfaces and/or classes that need them.
- Inheritance hierarchies must form a tree, that is you must avoid creating a circular dependency where, for example, Type A inherits from Type B, which inherits from Type `CCCCC`, which inherits from Type `AAAAA`.
- The super-Types (abstract class and interface) that a concrete class inherits from must not define conflicting members, e.g. members with the same name but having different Type signatures.
- See also example in interface 

## abstract class

An abstract class may not be instantiated (and hence may not define a constructor). It may define these concrete members:

- a property
- a function
- a procedure

As with a concrete class, any of these members may be made `privateprivateprivateprivateprivate`, after the corresponding instruction has been added, by selecting that member instruction and keying Ctrl+p.

These concrete members are automatically inherited by any subclass, but they may not be overridden (re-defined) by the subclass. Therefore you should define concrete members only if they are intended to work identically on every subclass.

You may also define abstract methods on an abstract class, i.e. abstract property, abstract function, abstract procedure. Such methods define only the signature of the method, not the implementation (body), therefore they have no `endendendendend` instruction. For example:

+function calculateDiscount name?(a as Float, d as Float parameter definitions?) returns Float Type? 1 let discount name? be a*d value or expression?2 return discount value or expression?3 end function
+def calculateDiscount name?(a: float, d: float parameter definitions?) -> float Type?: # function 1 discount name? = a*d value or expression? # let 2 return discount value or expression?3
+static double Type? calculateDiscount name?(double a, double d parameter definitions?) { // function 1 var discount name? = a*d value or expression?; // let 2 return discount value or expression?;3 } // function
+Function calculateDiscount name?(a As Double, d As Double parameter definitions?) As Double Type? 1 Dim discount name? = a*d value or expression? ' let 2 Return discount value or expression?3 End Function
+static double Type? calculateDiscount name?(double a, double d parameter definitions?) { // function 1 var discount name? = a*d value or expression?; // let 2 return discount value or expression?;3 } // function

If you wish to have several subclasses of an abstract class that share a common implementation for a method, but require that some of the subclasses can define a different implementation, then you should:

- Define the method as abstract on the superclass.
- Define a concrete implementation on the superclass with a similar, but slightly different, name e.g. by adding a prefix such as: `defaultdefaultdefaultdefaultdefault`.
- Each subclass must then define its implementation of the abstract method, but the ones needing a common implementation can be just one line, delegating responsibility up to the 'default' method on the superclass.

## interface

An interface is similar to an abstract class, with the difference that it may define only abstract members. The advantage of using an interface instead of an abstract class is that a concrete class can inherit from multiple interfaces.

An interface may inherit only from other interfaces.

An interface must not re-declare abstract interfaces that are defined in any interface it inherits from, directly or indirectly.

#### Example using interface

● Example from some code in demo program blackjack of:

- inheritance from interface `PlayerPlayerPlayerPlayerPlayer` to abstract class `AutomatedAutomatedAutomatedAutomatedAutomated` and to concrete class `HumanPlayerHumanPlayerHumanPlayerHumanPlayerHumanPlayer`, and
- inheritance from abstract class `AutomatedAutomatedAutomatedAutomatedAutomated` to concrete class `DealerDealerDealerDealerDealer`
- (concrete) definitions of function getAction and procedure changeScoreBy following their abstract declarations.

enum PlayerAction Name? stand, draw values?values?1 +interface Player Name? inheritance?2 abstract property hand name? as Hand Type?3 abstract procedure changeScoreBy name?(amount as Int parameter definitions?)4 end interface +abstract class Automated Name? inherits Player inheritance? inheritance?5 property hand name? as Hand Type?6 property score name? as Int Type?7 abstract function getAction name?(parameter definitions parameter definitions?) returns PlayerAction Type?8 +procedure changeScoreBy name?(amount as Int parameter definitions?) 9 reassign this.score variableName? to this.score + amount value or expression?10 end procedure end abstract class +class Dealer Name? inherits Automated inheritance? inheritance?11 +constructor(startingPoints as Int parameter definitions?) 12 reassign this.score variableName? to startingPoints value or expression?13 reassign this.hand variableName? to this.hand value or expression?14 end constructor +function getAction name?(parameter definitions parameter definitions?) returns PlayerAction Type? 15 return if((this.hand.total < 17), PlayerAction.draw, PlayerAction.stand)value or expression?16 end function +function toString name?(parameter definitions parameter definitions?) returns String Type? 17 return "a Dealer"value or expression?18 end function end class +class HumanPlayer Name? inherits Player inheritance? inheritance?19 +constructor(startingPoints as Int, hand as Hand parameter definitions?) 20 reassign this.hand variableName? to hand value or expression?21 end constructor property hand name? as Hand Type?22 +procedure changeScoreBy name?(amount as Int parameter definitions?) 23 new code end procedure +function toString name?(parameter definitions parameter definitions?) returns String Type? 24 return "a HumanPlayer"value or expression?25 end function end class +class Hand Name? inheritance?26 +constructor(parameter definitions parameter definitions?) 27 reassign this.total variableName? to 0 value or expression?28 end constructor property total name? as Int Type?29 +function toString name?(parameter definitions parameter definitions?) returns String Type? 30 return "a Hand"value or expression?31 end function end class
class PlayerAction Name?(Enum):
stand = 1
draw = 2 values?1 +class Player Name?(ABC) inheritance? # interface 2 @property
@abstractmethod
def hand name?(self: Player) -> Hand Type?:
pass # abstract property 3 @abstractmethod
def changeScoreBy name?(amount: int parameter definitions?) -> None
pass # abstract procedure 4 +class Automated Name?(Player inheritance?) inheritance? # abstract class 5 hand name?: Hand Type? # property 6 score name?: int Type? # property 7 @abstractmethod
def getAction name?(parameter definitions parameter definitions?) -> PlayerAction Type?:
pass # abstract function 8 +def changeScoreBy name?(self: Automated, amount: int parameter definitions?) -> None: # procedure method 9 self.score variableName? = self.score + amount value or expression? # reassign variable 10 +class Dealer Name?(Automated inheritance?) inheritance? # concrete class 11 +def __init__(self: Dealer, startingPoints: int parameter definitions?) -> None: 12 self.score variableName? = startingPoints value or expression? # reassign variable 13 self.hand variableName? = self.hand value or expression? # reassign variable 14 +def getAction name?(self: Dealer) -> PlayerAction Type?: # function method 15 return if((self.hand.total < 17), PlayerAction.draw, PlayerAction.stand)value or expression?16 +def toString name?(self: Dealer) -> str Type?: # function method 17 return "a Dealer"value or expression?18 +class HumanPlayer Name?(Player inheritance?) inheritance? # concrete class 19 +def __init__(self: HumanPlayer, startingPoints: int, hand: Hand parameter definitions?) -> None: 20 self.hand variableName? = hand value or expression? # reassign variable 21 hand name?: Hand Type? # property 22 +def changeScoreBy name?(self: HumanPlayer, amount: int parameter definitions?) -> None: # procedure method 23 new code +def toString name?(self: HumanPlayer) -> str Type?: # function method 24 return "a HumanPlayer"value or expression?25 +class Hand Name? inheritance? # concrete class 26 +def __init__(self: Hand) -> None: 27 self.total variableName? = 0 value or expression? # reassign variable 28 total name?: int Type? # property 29 +def toString name?(self: Hand) -> str Type?: # function method 30 return "a Hand"value or expression?31
enum PlayerAction Name? {stand, draw values?values?}1 +interface Player Name? inheritance? {2 abstract Hand Type? hand name? {get; private set;} // abstract property 3 abstract void changeScoreBy name?(int amount parameter definitions?); // abstract procedure 4 } // interface +abstract class Automated Name?: Player inheritance? inheritance? {5 public Hand Type? hand name? {get; private set;} // property 6 public int Type? score name? {get; private set;} // property 7 abstract PlayerAction Type? getAction name?(parameter definitions parameter definitions?); // abstract function 8 +public void changeScoreBy name?(int amount parameter definitions?) { // procedure method 9 this.score variableName? = this.score + amount value or expression?; // reassign variable 10 } // procedure method } // class +class Dealer Name?: Automated inheritance? inheritance? {11 +public Dealer(int startingPoints parameter definitions?) { 12 this.score variableName? = startingPoints value or expression?; // reassign variable 13 this.hand variableName? = this.hand value or expression?; // reassign variable 14 } // constructor +public override PlayerAction Type? getAction name?(parameter definitions parameter definitions?) { // function method 15 return if((this.hand.total < 17), PlayerAction.draw, PlayerAction.stand)value or expression?;16 } // function method +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 17 return "a Dealer"value or expression?;18 } // function method } // class +class HumanPlayer Name?: Player inheritance? inheritance? {19 +public HumanPlayer(int startingPoints, Hand hand parameter definitions?) { 20 this.hand variableName? = hand value or expression?; // reassign variable 21 } // constructor public Hand Type? hand name? {get; private set;} // property 22 +public void changeScoreBy name?(int amount parameter definitions?) { // procedure method 23 new code } // procedure method +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 24 return "a HumanPlayer"value or expression?;25 } // function method } // class +class Hand Name? inheritance? {26 +public Hand(parameter definitions parameter definitions?) { 27 this.total variableName? = 0 value or expression?; // reassign variable 28 } // constructor public int Type? total name? {get; private set;} // property 29 +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 30 return "a Hand"value or expression?;31 } // function method } // class
Enum PlayerAction Name?
stand = 0
draw = 1
End Enum values?1 +Interface Player Name? inheritance? inheritance?2 MustOverride Property hand name? As Hand Type?3 MustOverride Sub changeScoreBy name?(amount As Integer parameter definitions?)4 End Interface +MustInherit Class Automated Name?
Implements Player
inheritance?5 Property hand name? As Hand Type?6 Property score name? As Integer Type?7 MustOverride Function getAction name?(parameter definitions parameter definitions?) As PlayerAction Type?8 +Sub changeScoreBy name?(amount As Integer parameter definitions?) Implements Player.changeScoreBy name? ' procedure method 9 Me.score variableName? = Me.score + amount value or expression? ' reassign variable 10 End Sub End Class +Class Dealer Name?
Inherits Automated
inheritance?11 +Sub New(startingPoints As Integer parameter definitions?) 12 Me.score variableName? = startingPoints value or expression? ' reassign variable 13 Me.hand variableName? = Me.hand value or expression? ' reassign variable 14 End Sub +Overrides Function getAction name?(parameter definitions parameter definitions?) As PlayerAction Type? 15 Return if((Me.hand.total < 17), PlayerAction.draw, PlayerAction.stand)value or expression?16 End Function +Function toString name?(parameter definitions parameter definitions?) As String Type? 17 Return "a Dealer"value or expression?18 End Function End Class +Class HumanPlayer Name?
Implements Player
inheritance?19 +Sub New(startingPoints As Integer, hand As Hand parameter definitions?) 20 Me.hand variableName? = hand value or expression? ' reassign variable 21 End Sub Property hand name? As Hand Type?22 +Sub changeScoreBy name?(amount As Integer parameter definitions?) Implements Player.changeScoreBy name? ' procedure method 23 new code End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 24 Return "a HumanPlayer"value or expression?25 End Function End Class +Class Hand Name? inheritance? inheritance?26 +Sub New(parameter definitions parameter definitions?) 27 Me.total variableName? = 0 value or expression? ' reassign variable 28 End Sub Property total name? As Integer Type?29 +Function toString name?(parameter definitions parameter definitions?) As String Type? 30 Return "a Hand"value or expression?31 End Function End Class
enum PlayerAction Name? {stand, draw values?values?}1 +interface Player Name? inheritance? inheritance? {2 abstract Hand Type? hand name?; // abstract property 3 abstract void changeScoreBy name?(int amount parameter definitions?); // abstract procedure 4 } // interface +abstract class Automated Name? implements Player inheritance? {5 public Hand Type? hand name?; // property 6 public int Type? score name?; // property 7 abstract PlayerAction Type? getAction name?(parameter definitions parameter definitions?); // abstract function 8 +public void changeScoreBy name?(int amount parameter definitions?) { // procedure method 9 this.score variableName? = this.score + amount value or expression?; // reassign variable 10 } // procedure method } // class +class Dealer Name? extends Automated inheritance? {11 +public Dealer(int startingPoints parameter definitions?) { 12 this.score variableName? = startingPoints value or expression?; // reassign variable 13 this.hand variableName? = this.hand value or expression?; // reassign variable 14 } // constructor +public PlayerAction Type? getAction name?(parameter definitions parameter definitions?) { // function method 15 return if((this.hand.total < 17), PlayerAction.draw, PlayerAction.stand)value or expression?;16 } // function method +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 17 return "a Dealer"value or expression?;18 } // function method } // class +class HumanPlayer Name? implements Player inheritance? {19 +public HumanPlayer(int startingPoints, Hand hand parameter definitions?) { 20 this.hand variableName? = hand value or expression?; // reassign variable 21 } // constructor public Hand Type? hand name?; // property 22 +public void changeScoreBy name?(int amount parameter definitions?) { // procedure method 23 new code } // procedure method +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 24 return "a HumanPlayer"value or expression?;25 } // function method } // class +class Hand Name? inheritance? inheritance? {26 +public Hand(parameter definitions parameter definitions?) { 27 this.total variableName? = 0 value or expression?; // reassign variable 28 } // constructor public int Type? total name?; // property 29 +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 30 return "a Hand"value or expression?;31 } // function method } // class

## constant

A constant instruction defines a named value that is defined at the global level in a program, is global in scope and cannot be changed. Its name follows the rules for an identifier .

A constant is defined by a literal of a value Type, namely `IntintintIntegerint`, `FloatfloatdoubleDoubledouble`, `BooleanboolboolBooleanbool` or `StringstrstringStringString`.

Constants are created at compile time, so cannot be defined with reference to any function, nor can they use any operators in an expression.

A constant can be defined by reference to a previously defined constant or to a system constant, but take care not to re-define a system constant  such as pi or blue without good reason.

A 'constant' data structure can be defined by using a function which is then referenced from wherever needed. See Constant data structures .

Examples of literal definitions of the valid Types of constant:

+constant maxHits name? set to 10 literal value or data structure?1 +constant turquoise name? set to 0x00ced1 literal value or data structure?2 +constant liveCell name? set to black literal value or data structure?3 +constant speedOfLight name? set to 299792.458 literal value or data structure?4 +constant gameOver name? set to true literal value or data structure?5 +constant euro name? set to 0x20ac literal value or data structure?6 +constant warningMsg name? set to "Limit reached"literal value or data structure?7
+maxHits name? = 10 literal value or data structure? # constant 1 +turquoise name? = 0x00ced1 literal value or data structure? # constant 2 +liveCell name? = black literal value or data structure? # constant 3 +speedOfLight name? = 299792.458 literal value or data structure? # constant 4 +gameOver name? = True literal value or data structure? # constant 5 +euro name? = 0x20ac literal value or data structure? # constant 6 +warningMsg name? = "Limit reached"literal value or data structure? # constant 7
+const Int maxHits name? = 10 literal value or data structure?1 +const Int turquoise name? = 0x00ced1 literal value or data structure?2 +const Int liveCell name? = black literal value or data structure?3 +const Float speedOfLight name? = 299792.458 literal value or data structure?4 +const Boolean gameOver name? = true literal value or data structure?5 +const Int euro name? = 0x20ac literal value or data structure?6 +const String warningMsg name? = "Limit reached"literal value or data structure?7
+Const maxHits name? = 10 literal value or data structure?1 +Const turquoise name? = &H00ced1 literal value or data structure?2 +Const liveCell name? = black literal value or data structure?3 +Const speedOfLight name? = 299792.458 literal value or data structure?4 +Const gameOver name? = True literal value or data structure?5 +Const euro name? = &H20ac literal value or data structure?6 +Const warningMsg name? = "Limit reached"literal value or data structure?7
+final Int maxHits name? = 10 literal value or data structure? // constant 1 +final Int turquoise name? = 0x00ced1 literal value or data structure? // constant 2 +final Int liveCell name? = black literal value or data structure? // constant 3 +final Float speedOfLight name? = 299792.458 literal value or data structure? // constant 4 +final Boolean gameOver name? = true literal value or data structure? // constant 5 +final Int euro name? = 0x20ac literal value or data structure? // constant 6 +final String warningMsg name? = "Limit reached"literal value or data structure? // constant 7

### Constant data structures

To use a data structure that is to be a constant in your program, you define it as the value of a function which cam then be referenced from anywhere in the program, often from within an expression.

These examples define a constant `ListlistListListList` and a constant `DictionaryDictionaryDictionaryDictionaryDictionary` of colours which are indexable:

+main 1 call print procedureName?($"{rainbow()[0]} is violet"arguments?)2 call print procedureName?($"{suitColours()["hearts"]} is red"arguments?)3 end main +function rainbow name?(parameter definitions parameter definitions?) returns List<of Int>Type? 4 return [0x9400D3, 0x4B0082, 0x0000CD, 0x008000, 0xFFFF00, 0xFFA500, 0xFF0000]value or expression?5 end function +function suitColours name?(parameter definitions parameter definitions?) returns Dictionary<of String, Int>Type? 6 return ["spades":black, "hearts":red, "diamonds":red, "clubs":black]value or expression?7 end function
+def main() -> None: 1 print procedureName?(f"{rainbow()[0]} is violet"arguments?)2 print procedureName?(f"{suitColours()["hearts"]} is red"arguments?)3 +def rainbow name?(parameter definitions parameter definitions?) -> list[int]Type?: # function 4 return [0x9400D3, 0x4B0082, 0x0000CD, 0x008000, 0xFFFF00, 0xFFA500, 0xFF0000]value or expression?5 +def suitColours name?(parameter definitions parameter definitions?) -> Dictionary[str, int]Type?: # function 6 return ["spades":black, "hearts":red, "diamonds":red, "clubs":black]value or expression?7 main()
+static void main() { 1 print procedureName?($"{rainbow()[0]} is violet"arguments?);2 print procedureName?($"{suitColours()["hearts"]} is red"arguments?);3 } // main +static List<int>Type? rainbow name?(parameter definitions parameter definitions?) { // function 4 return [0x9400D3, 0x4B0082, 0x0000CD, 0x008000, 0xFFFF00, 0xFFA500, 0xFF0000]value or expression?;5 } // function +static Dictionary<string, int>Type? suitColours name?(parameter definitions parameter definitions?) { // function 6 return ["spades":black, "hearts":red, "diamonds":red, "clubs":black]value or expression?;7 } // function
+Sub main() 1 print procedureName?($"{rainbow()[0]} is violet"arguments?)2 print procedureName?($"{suitColours()["hearts"]} is red"arguments?)3 End Sub +Function rainbow name?(parameter definitions parameter definitions?) As List(Of Integer)Type? 4 Return {&H9400D3, &H4B0082, &H0000CD, &H008000, &HFFFF00, &HFFA500, &HFF0000}value or expression?5 End Function +Function suitColours name?(parameter definitions parameter definitions?) As Dictionary(Of String, Integer)Type? 6 Return ["spades":black, "hearts":red, "diamonds":red, "clubs":black]value or expression?7 End Function
+static void main() { 1 print procedureName?(String.format("% is violet", rainbow()[0])arguments?);2 print procedureName?(String.format("% is red", suitColours()["hearts"])arguments?);3 } // main +static List<int>Type? rainbow name?(parameter definitions parameter definitions?) { // function 4 return [0x9400D3, 0x4B0082, 0x0000CD, 0x008000, 0xFFFF00, 0xFFA500, 0xFF0000]value or expression?;5 } // function +static Dictionary<String, int>Type? suitColours name?(parameter definitions parameter definitions?) { // function 6 return ["spades":black, "hearts":red, "diamonds":red, "clubs":black]value or expression?;7 } // function

### System constants

Some useful constants are provided: see System constants 

## enum

An enum – short for 'enumeration' – provides for the simplest form of user-defined Type. It is used to provide a fixed set of options that are self-explanatory, and the references to its those options (its 'values') are checked at compile time.

You define an enum with a Type name (so starting with an uppercase letter) followed by a number of 'values' (separated by commas) which must all be valid identifiers .

A reference to an enum by its Type name necessarily holds one of the 'values'.

Reference to the value in an enum is made by using dot syntax  with method enumValue.

An enum is read-only: once it has been defined it is not possible to add, remove, or update its values.

Examples of enum definitions:

enum Suit Name? spades, hearts, diamonds, clubs values?values?1 enum Outcome Name? undecided, win, lose, draw, winDouble values?values?2
class Suit Name?(Enum):
spades = 1
hearts = 2
diamonds = 3
clubs = 4 values?1 class Outcome Name?(Enum):
undecided = 1
win = 2
lose = 3
draw = 4
winDouble = 5 values?2
enum Suit Name? {spades, hearts, diamonds, clubs values?values?}1 enum Outcome Name? {undecided, win, lose, draw, winDouble values?values?}2
Enum Suit Name?
spades = 0
hearts = 1
diamonds = 2
clubs = 3
End Enum values?1 Enum Outcome Name?
undecided = 0
win = 1
lose = 2
draw = 3
winDouble = 4
End Enum values?2
enum Suit Name? {spades, hearts, diamonds, clubs values?values?}1 enum Outcome Name? {undecided, win, lose, draw, winDouble values?values?}2

#### Examples using enum

● To retrieve a valid 'value':

enum Status Name? pending, playing, standing, blackjack, bust values?values?1 +main 2 variable state name? set to Status.pending value or expression?3 end main
class Status Name?(Enum):
pending = 1
playing = 2
standing = 3
blackjack = 4
bust = 5 values?1 +def main() -> None: 2 state name? = Status.pending value or expression? # variable definition 3 main()
enum Status Name? {pending, playing, standing, blackjack, bust values?values?}1 +static void main() { 2 var state name? = Status.pending value or expression?;3 } // main
Enum Status Name?
pending = 0
playing = 1
standing = 2
blackjack = 3
bust = 4
End Enum values?1 +Sub main() 2 Dim state name? = Status.pending value or expression? ' variable definition 3 End Sub
enum Status Name? {pending, playing, standing, blackjack, bust values?values?}1 +static void main() { 2 var state name? = Status.pending value or expression?;3 } // main

● To get a valid option from an abbreviation (in demo program pathfinder.elan):

enum Algorithm Name? dijkstra, aStar, heuristic values?values?1 +function getAlgFromLetter name?(letter as String parameter definitions?) returns Algorithm Type? 2 variable algs name? set to ["a":Algorithm.aStar, "d":Algorithm.dijkstra, "h":Algorithm.heuristic]value or expression?3 return algs[letter]value or expression?4 end function
class Algorithm Name?(Enum):
dijkstra = 1
aStar = 2
heuristic = 3 values?1 +def getAlgFromLetter name?(letter: str parameter definitions?) -> Algorithm Type?: # function 2 algs name? = ["a":Algorithm.aStar, "d":Algorithm.dijkstra, "h":Algorithm.heuristic]value or expression? # variable definition 3 return algs[letter]value or expression?4
enum Algorithm Name? {dijkstra, aStar, heuristic values?values?}1 +static Algorithm Type? getAlgFromLetter name?(string letter parameter definitions?) { // function 2 var algs name? = ["a":Algorithm.aStar, "d":Algorithm.dijkstra, "h":Algorithm.heuristic]value or expression?;3 return algs[letter]value or expression?;4 } // function
Enum Algorithm Name?
dijkstra = 0
aStar = 1
heuristic = 2
End Enum values?1 +Function getAlgFromLetter name?(letter As String parameter definitions?) As Algorithm Type? 2 Dim algs name? = ["a":Algorithm.aStar, "d":Algorithm.dijkstra, "h":Algorithm.heuristic]value or expression? ' variable definition 3 Return algs[letter]value or expression?4 End Function
enum Algorithm Name? {dijkstra, aStar, heuristic values?values?}1 +static Algorithm Type? getAlgFromLetter name?(String letter parameter definitions?) { // function 2 var algs name? = ["a":Algorithm.aStar, "d":Algorithm.dijkstra, "h":Algorithm.heuristic]value or expression?;3 return algs[letter]value or expression?;4 } // function

● A function to turn directions held in an enum through 90° clockwise:

enum Compass Name? north, east, south, west values?values?1 +main 2 variable dir name? set to Compass.south value or expression?3 call print procedureName?(enumValue(clockwise(dir))arguments?)4 end main +function clockwise name?(d as Compass parameter definitions?) returns Compass Type? 5 variable newDir name? set to Compass.north value or expression?6 +if d.equals(Compass.north)condition? then 7 reassign newDir variableName? to Compass.east value or expression?8 elif d.equals(Compass.east)condition? then 9 reassign newDir variableName? to Compass.south value or expression?10 elif d.equals(Compass.south)condition? then 11 reassign newDir variableName? to Compass.west value or expression?12 end if return newDir value or expression?13 end function
class Compass Name?(Enum):
north = 1
east = 2
south = 3
west = 4 values?1 +def main() -> None: 2 dir name? = Compass.south value or expression? # variable definition 3 print procedureName?(enumValue(clockwise(dir))arguments?)4 +def clockwise name?(d: Compass parameter definitions?) -> Compass Type?: # function 5 newDir name? = Compass.north value or expression? # variable definition 6 +if d.equals(Compass.north)condition?: 7 newDir variableName? = Compass.east value or expression? # reassign variable 8 elif d.equals(Compass.east)condition?: # else if 9 newDir variableName? = Compass.south value or expression? # reassign variable 10 elif d.equals(Compass.south)condition?: # else if 11 newDir variableName? = Compass.west value or expression? # reassign variable 12 return newDir value or expression?13 main()
enum Compass Name? {north, east, south, west values?values?}1 +static void main() { 2 var dir name? = Compass.south value or expression?;3 print procedureName?(enumValue(clockwise(dir))arguments?);4 } // main +static Compass Type? clockwise name?(Compass d parameter definitions?) { // function 5 var newDir name? = Compass.north value or expression?;6 +if (d.equals(Compass.north)condition?) { 7 newDir variableName? = Compass.east value or expression?; // reassign variable 8 } else if (d.equals(Compass.east)condition?) {9 newDir variableName? = Compass.south value or expression?; // reassign variable 10 } else if (d.equals(Compass.south)condition?) {11 newDir variableName? = Compass.west value or expression?; // reassign variable 12 } // if return newDir value or expression?;13 } // function
Enum Compass Name?
north = 0
east = 1
south = 2
west = 3
End Enum values?1 +Sub main() 2 Dim dir name? = Compass.south value or expression? ' variable definition 3 print procedureName?(enumValue(clockwise(dir))arguments?)4 End Sub +Function clockwise name?(d As Compass parameter definitions?) As Compass Type? 5 Dim newDir name? = Compass.north value or expression? ' variable definition 6 +If d.equals(Compass.north)condition? Then 7 newDir variableName? = Compass.east value or expression? ' reassign variable 8 ElseIf d.equals(Compass.east)condition? Then 9 newDir variableName? = Compass.south value or expression? ' reassign variable 10 ElseIf d.equals(Compass.south)condition? Then 11 newDir variableName? = Compass.west value or expression? ' reassign variable 12 End If Return newDir value or expression?13 End Function
enum Compass Name? {north, east, south, west values?values?}1 +static void main() { 2 var dir name? = Compass.south value or expression?;3 print procedureName?(enumValue(clockwise(dir))arguments?);4 } // main +static Compass Type? clockwise name?(Compass d parameter definitions?) { // function 5 var newDir name? = Compass.north value or expression?;6 +if (d.equals(Compass.north)condition?) { 7 newDir variableName? = Compass.east value or expression?; // reassign variable 8 } else if (d.equals(Compass.east)condition?) {9 newDir variableName? = Compass.south value or expression?; // reassign variable 10 } else if (d.equals(Compass.south)condition?) {11 newDir variableName? = Compass.west value or expression?; // reassign variable 12 } // if return newDir value or expression?;13 } // function

# Member instructions

Member instructions (also referred to simply as 'members') are located within an interface, abstract class or concrete class. The new code prompt offers a context appropriate subset of the following member instructions:

abstract property , abstract function , abstract procedure , property , function method , procedure method  and constructor ,

together with these 'private' versions:

private property , private function  and private procedure .

This table shows which kinds of property, function, procedure and constructor are applicable to the various kinds of class.

| Abstract | Concrete | notes
--- | --- | --- | ---
| interface  | abstract class  | concrete class  |
abstract property  | ✔ | ✔ |  |
abstract function  | ✔ | ✔ |  | prototype for function reference only
abstract procedure  | ✔ | ✔ |  | prototype for procedure call only
property  |  | ✔ | ✔ |
function method  |  | ✔ | ✔ | method toString must be defined
procedure method  |  | ✔ | ✔ |
private property  |  |  | ✔ |
private function  |  |  | ✔ |
private procedure  |  |  | ✔ |
constructor  |  |  | ✔ |

## constructor

A concrete class may have an optional constructor so as to:

- initialise properties with fixed values
- define parameters which are used to initialise properties

If a concrete class's constructor defines parameters then, when the class is instantiated (using new), the values of the correct Type must be provided. For example, if the class `SquareSquareSquareSquareSquare` has this constructor:

+class Square Name? inheritance?1 +constructor(x as Int, y as Int parameter definitions?) 2 reassign this.x variableName? to x value or expression?3 reassign this.y variableName? to y value or expression?4 end constructor +function toString name?(parameter definitions?) returns String Type? 5 return "undefined"value or expression?6 end function end class
+class Square Name? inheritance? # concrete class 1 +def __init__(self: Square, x: int, y: int parameter definitions?) -> None: 2 self.x variableName? = x value or expression? # reassign variable 3 self.y variableName? = y value or expression? # reassign variable 4 +def toString name?(self: Square) -> str Type?: # function method 5 return "undefined"value or expression?6
+class Square Name? inheritance? {1 +public Square(int x, int y parameter definitions?) { 2 this.x variableName? = x value or expression?; // reassign variable 3 this.y variableName? = y value or expression?; // reassign variable 4 } // constructor +public string Type? toString name?(parameter definitions?) { // function method 5 return "undefined"value or expression?;6 } // function method } // class
+Class Square Name? inheritance? inheritance?1 +Sub New(x As Integer, y As Integer parameter definitions?) 2 Me.x variableName? = x value or expression? ' reassign variable 3 Me.y variableName? = y value or expression? ' reassign variable 4 End Sub +Function toString name?(parameter definitions?) As String Type? 5 Return "undefined"value or expression?6 End Function End Class
+class Square Name? inheritance? inheritance? {1 +public Square(int x, int y parameter definitions?) { 2 this.x variableName? = x value or expression?; // reassign variable 3 this.y variableName? = y value or expression?; // reassign variable 4 } // constructor +public String Type? toString name?(parameter definitions?) { // function method 5 return "undefined"value or expression?;6 } // function method } // class

then it may be instantiated like this:
`variable tailname? set to new Square(20, 15)value or expression?0tailname? = Square(20, 15)value or expression? # variable definition0var tailname? = new Square(20, 15)value or expression?;0Dim tailname? = New Square(20, 15)value or expression? ' variable definition0var tailname? = new Square(20, 15)value or expression?;0`

## property

A property is a named value defined on a concrete class with a name conforming to the rules for an identifier , and a Type (which may be another class name).

It may be read, but not written to: properties may be modified only from outside the class by means of a procedure method .

It may be given an initial value within a constructor, for example:

+class Game Name? inheritance?1 property height name? as Int Type?2 property board name? as Board Type?3 property head name? as Square Type?4 property body name? as List<of Square>Type?5 +constructor(parameter definitions parameter definitions?) 6 new code end constructor +function toString name?(parameter definitions parameter definitions?) returns String Type? 7 return "undefined"value or expression?8 end function end class
+class Game Name? inheritance? # concrete class 1 height name?: int Type? # property 2 board name?: Board Type? # property 3 head name?: Square Type? # property 4 body name?: list[Square]Type? # property 5 +def __init__(self: Game) -> None: 6 new code +def toString name?(self: Game) -> str Type?: # function method 7 return "undefined"value or expression?8
+class Game Name? inheritance? {1 public int Type? height name? {get; private set;} // property 2 public Board Type? board name? {get; private set;} // property 3 public Square Type? head name? {get; private set;} // property 4 public List<Square>Type? body name? {get; private set;} // property 5 +public Game(parameter definitions parameter definitions?) { 6 new code } // constructor +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 7 return "undefined"value or expression?;8 } // function method } // class
+Class Game Name? inheritance? inheritance?1 Property height name? As Integer Type?2 Property board name? As Board Type?3 Property head name? As Square Type?4 Property body name? As List(Of Square)Type?5 +Sub New(parameter definitions parameter definitions?) 6 new code End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 7 Return "undefined"value or expression?8 End Function End Class
+class Game Name? inheritance? inheritance? {1 public int Type? height name?; // property 2 public Board Type? board name?; // property 3 public Square Type? head name?; // property 4 public List<Square>Type? body name?; // property 5 +public Game(parameter definitions parameter definitions?) { 6 new code } // constructor +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 7 return "undefined"value or expression?;8 } // function method } // class

### `MaybeMaybeMaybeMaybeMaybe`

When a class property is optional, it is defined with the Type `MaybeMaybeMaybeMaybeMaybe`.

Before reading the property's value, you must test if it has a value with function hasValue which returns a `BooleanboolboolBooleanbool`. If `trueTruetrueTruetrue` is returned, then you retrieve the value with function getValue; if `falseFalsefalseFalsefalse` is returned, then it has no current value, and using getValue will give a runtime error.

To update the property's value, use function setValue. To restore it to having no value, use function clearValue.

#### Example using `MaybeMaybeMaybeMaybeMaybe`

● Here a pupil (of class Pupil) need not have a tutor (of class Teacher):

+main 1 variable tTom name? set to new Teacher()value or expression?2 variable pPete name? set to new Pupil()value or expression?3 +if pPete.tutor.hasValue()condition? then 4 call print procedureName?(pPete.tutor arguments?)5 end if call print procedureName?(p arguments?)6 end main +class Teacher Name? inheritance?7 +constructor(parameter definitions parameter definitions?) 8 new code end constructor +function toString name?(parameter definitions parameter definitions?) returns String Type? 9 return $"{this}"value or expression?10 end function end class +class Pupil Name? inheritance?11 +constructor(parameter definitions parameter definitions?) 12 reassign this.tutor variableName? to new Maybe<of Teacher>()value or expression?13 end constructor property tutor name? as Maybe<of Teacher>Type?14 +function toString name?(parameter definitions parameter definitions?) returns String Type? 15 return "undefined"value or expression?16 end function end class
+def main() -> None: 1 tTom name? = Teacher()value or expression? # variable definition 2 pPete name? = Pupil()value or expression? # variable definition 3 +if pPete.tutor.hasValue()condition?: 4 print procedureName?(pPete.tutor arguments?)5 print procedureName?(p arguments?)6 +class Teacher Name? inheritance? # concrete class 7 +def __init__(self: Teacher) -> None: 8 new code +def toString name?(self: Teacher) -> str Type?: # function method 9 return f"{self}"value or expression?10 +class Pupil Name? inheritance? # concrete class 11 +def __init__(self: Pupil) -> None: 12 self.tutor variableName? = Maybe[Teacher]()value or expression? # reassign variable 13 tutor name?: Maybe[Teacher]Type? # property 14 +def toString name?(self: Pupil) -> str Type?: # function method 15 return "undefined"value or expression?16 main()
+static void main() { 1 var tTom name? = new Teacher()value or expression?;2 var pPete name? = new Pupil()value or expression?;3 +if (pPete.tutor.hasValue()condition?) { 4 print procedureName?(pPete.tutor arguments?);5 } // if print procedureName?(p arguments?);6 } // main +class Teacher Name? inheritance? {7 +public Teacher(parameter definitions parameter definitions?) { 8 new code } // constructor +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 9 return $"{this}"value or expression?;10 } // function method } // class +class Pupil Name? inheritance? {11 +public Pupil(parameter definitions parameter definitions?) { 12 this.tutor variableName? = new Maybe<Teacher>()value or expression?; // reassign variable 13 } // constructor public Maybe<Teacher>Type? tutor name? {get; private set;} // property 14 +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 15 return "undefined"value or expression?;16 } // function method } // class
+Sub main() 1 Dim tTom name? = New Teacher()value or expression? ' variable definition 2 Dim pPete name? = New Pupil()value or expression? ' variable definition 3 +If pPete.tutor.hasValue()condition? Then 4 print procedureName?(pPete.tutor arguments?)5 End If print procedureName?(p arguments?)6 End Sub +Class Teacher Name? inheritance? inheritance?7 +Sub New(parameter definitions parameter definitions?) 8 new code End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 9 Return $"{Me}"value or expression?10 End Function End Class +Class Pupil Name? inheritance? inheritance?11 +Sub New(parameter definitions parameter definitions?) 12 Me.tutor variableName? = New Maybe(Of Teacher)()value or expression? ' reassign variable 13 End Sub Property tutor name? As Maybe(Of Teacher)Type?14 +Function toString name?(parameter definitions parameter definitions?) As String Type? 15 Return "undefined"value or expression?16 End Function End Class
+static void main() { 1 var tTom name? = new Teacher()value or expression?;2 var pPete name? = new Pupil()value or expression?;3 +if (pPete.tutor.hasValue()condition?) { 4 print procedureName?(pPete.tutor arguments?);5 } // if print procedureName?(p arguments?);6 } // main +class Teacher Name? inheritance? inheritance? {7 +public Teacher(parameter definitions parameter definitions?) { 8 new code } // constructor +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 9 return String.format("%", this)value or expression?;10 } // function method } // class +class Pupil Name? inheritance? inheritance? {11 +public Pupil(parameter definitions parameter definitions?) { 12 this.tutor variableName? = new Maybe<Teacher>()value or expression?; // reassign variable 13 } // constructor public Maybe<Teacher>Type? tutor name?; // property 14 +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 15 return "undefined"value or expression?;16 } // function method } // class

## function method

A function method follows the same syntax and rules as a global function . The differences are:

- A `functionfunctionfunctionfunctionfunction` method is always referenced (used) by code outside the class using dot syntax  on an instance.
- A `functionfunctionfunctionfunctionfunction` method may directly reference (read only) any property defined on the class as though it were a variable or parameter.
- A `functionfunctionfunctionfunctionfunction` method may be marked `privateprivateprivateprivateprivate`, in which case it is visible only to code within the class and, if defined on abstract class `AAAAA`, within its subclasses. This is done by selecting the property instruction and then keying Ctrl+p. (Pressing these keys again will remove the `privateprivateprivateprivateprivate` modifier).
- toString method is just a regular function method with the specific name, takes no parameters and and returns a value of type `StringstrstringStringString`. If defined for a class then, if an instance of the class is printed, function method toString will automatically be used. Typically toString will return a string made up of one or more of the property values, perhaps with additional text, or the results of function calls.

## procedure method

A 'procedure method' follows the same syntax and rules as a global procedure . The differences are:

- A procedure method, like a function method, is always referenced (used) by code outside the class using dot syntax  on an instance.
- A procedure method may read, or write to, any property defined on the class.
- A procedure method may be marked `privateprivateprivateprivateprivate`, in which case it is visible only to code within the class and, if defined on an abstract `classclassclassclassclass`, within its subclasses. This is done by selecting the property instruction and then keying Ctrl+p. (Pressing these keys again will remove the `privateprivateprivateprivateprivate` modifier).

## abstract property

An abstract `propertypropertypropertypropertyproperty` may be defined only on an abstract class . Any concrete subclass must then implement a concrete (regular) property to match.

## abstract function

An abstract function method may be defined only on an abstract class . Any concrete subclass must then implement a concrete (regular) function to match.

## abstract procedure

An abstract procedure method may be defined only on an abstract class . Any concrete subclass must then implement a concrete (regular) procedure to match.

## private (property, function, procedure)

A property may be marked private, in which case it is visible only to code within the class and, if defined on an abstract class, within its subclasses. This is done by using the context menu on the property instruction or selecting it and keying Ctrl+p. This action is a toggle used both to reassign and to remove the modifier private.

- A property that is not private may be read, but not written to.
- A property that is private may

- Whenever you wish to access a property from within a method (or from within the constructor) on the same class, then the name of the property must be prefixed with the 'qualifier': `propertypropertypropertypropertyproperty`.('property-dot'). This applies whether you are reading or setting the property. By this means you can have a method parameter with the same name as a property, but they are unambiguous, because the property must be prefixed. A common pattern is to use the same name in a 'setter' method, for example:

+class Game Name? inheritance?1 +constructor(board as Board parameter definitions?) 2 reassign this.board variableName? to board value or expression?3 end constructor +procedure setHeight name?(height as Int parameter definitions?) 4 reassign this.height variableName? to height value or expression?5 end procedure +function toString name?(parameter definitions?) returns String Type? 6 return "undefined"value or expression?7 end function end class
+class Game Name? inheritance? # concrete class 1 +def __init__(self: Game, board: Board parameter definitions?) -> None: 2 self.board variableName? = board value or expression? # reassign variable 3 +def setHeight name?(self: Game, height: int parameter definitions?) -> None: # procedure method 4 self.height variableName? = height value or expression? # reassign variable 5 +def toString name?(self: Game) -> str Type?: # function method 6 return "undefined"value or expression?7
+class Game Name? inheritance? {1 +public Game(Board board parameter definitions?) { 2 this.board variableName? = board value or expression?; // reassign variable 3 } // constructor +public void setHeight name?(int height parameter definitions?) { // procedure method 4 this.height variableName? = height value or expression?; // reassign variable 5 } // procedure method +public string Type? toString name?(parameter definitions?) { // function method 6 return "undefined"value or expression?;7 } // function method } // class
+Class Game Name? inheritance? inheritance?1 +Sub New(board As Board parameter definitions?) 2 Me.board variableName? = board value or expression? ' reassign variable 3 End Sub +Sub setHeight name?(height As Integer parameter definitions?) ' procedure method 4 Me.height variableName? = height value or expression? ' reassign variable 5 End Sub +Function toString name?(parameter definitions?) As String Type? 6 Return "undefined"value or expression?7 End Function End Class
+class Game Name? inheritance? inheritance? {1 +public Game(Board board parameter definitions?) { 2 this.board variableName? = board value or expression?; // reassign variable 3 } // constructor +public void setHeight name?(int height parameter definitions?) { // procedure method 4 this.height variableName? = height value or expression?; // reassign variable 5 } // procedure method +public String Type? toString name?(parameter definitions?) { // function method 6 return "undefined"value or expression?;7 } // function method } // class

# Statement instructions

Statement instructions (sometimes referred to as 'statements') are the imperative instructions used in the methods (procedural logic) of a program, and are:

variable definition , reassign variable , if , while loop , for loop , call procedure , try , throw  and, within a test, assert equal .

## variable definition

The variable definition .. set to .. instruction declares and initialises a mutable named valued. The name defined must be a valid identifier .>/p>

The initial value is given by a following expression. For example: `variable notename? set to 440value or expression?0notename? = 440value or expression? # variable definition0var notename? = 440value or expression?;0Dim notename? = 440value or expression? ' variable definition0var notename? = 440value or expression?;0`

## reassign variable

The `reassign avariableName? to bvalue or expression?0avariableName? = bvalue or expression? # reassign variable0avariableName? = bvalue or expression?; // reassign variable0avariableName? = bvalue or expression? ' reassign variable0avariableName? = bvalue or expression?; // reassign variable0` instruction assigns a new value to an existing named value: the value in `bbbbb` is copied into the named value `aaaaa`

The two named values must be of the same Type.

A reassign variable instruction may not assign a new value to a parameter within a procedure.

To change the value of an argument supplied in a procedure call, the corresponding parameter must have been defined as of Type `AsRefAsRefAsRefAsRefAsRef`, which then allows use of the dot method set on it. See Call by reference 

## if (instruction)

The if instruction specifies which of several code sequences is to be executed next.

- It is structured like this:
  +if (x < 1)condition? then 0 reassign x variableName? to 1 value or expression?1 elif x < 2 condition? then 2 reassign x variableName? to 2 value or expression?3 elif x < 3 condition? then 4 reassign x variableName? to 3 value or expression?5 else 6 reassign x variableName? to 0 value or expression?7 end if
  +if (x < 1)condition?: 0 x variableName? = 1 value or expression? # reassign variable 1 elif x < 2 condition?: # else if 2 x variableName? = 2 value or expression? # reassign variable 3 elif x < 3 condition?: # else if 4 x variableName? = 3 value or expression? # reassign variable 5 else:6 x variableName? = 0 value or expression? # reassign variable 7
  +if ((x < 1)condition?) { 0 x variableName? = 1 value or expression?; // reassign variable 1 } else if (x < 2 condition?) {2 x variableName? = 2 value or expression?; // reassign variable 3 } else if (x < 3 condition?) {4 x variableName? = 3 value or expression?; // reassign variable 5 } else {6 x variableName? = 0 value or expression?; // reassign variable 7 } // if
  +If (x < 1)condition? Then 0 x variableName? = 1 value or expression? ' reassign variable 1 ElseIf x < 2 condition? Then 2 x variableName? = 2 value or expression? ' reassign variable 3 ElseIf x < 3 condition? Then 4 x variableName? = 3 value or expression? ' reassign variable 5 Else 6 x variableName? = 0 value or expression? ' reassign variable 7 End If
  +if ((x < 1)condition?) { 0 x variableName? = 1 value or expression?; // reassign variable 1 } else if (x < 2 condition?) {2 x variableName? = 2 value or expression?; // reassign variable 3 } else if (x < 3 condition?) {4 x variableName? = 3 value or expression?; // reassign variable 5 } else {6 x variableName? = 0 value or expression?; // reassign variable 7 } // if
- The conditions, one of which is shown above enclosed in brackets, are Boolean values or expressions.
- else if and else clauses are optional.
- You can add as many else if clauses as you wish, but only one unconditional else which, if present, must be last.

See also if (expression)  for using the related if to return a value.

#### Examples using if instruction

● Simple choice between equality and inequality:

+if head is apple condition? then 0 call setAppleToRandomPosition procedureName?(apple, body arguments?)1 else 2 call body.removeAt procedureName?(0 arguments?)3 end if
+if head == apple condition?: 0 setAppleToRandomPosition procedureName?(apple, body arguments?) # call procedure 1 else:2 body.removeAt procedureName?(0 arguments?) # call procedure 3
+if (head == apple condition?) { 0 setAppleToRandomPosition procedureName?(apple, body arguments?); // call procedure 1 } else {2 body.removeAt procedureName?(0 arguments?); // call procedure 3 } // if
+If head = apple condition? Then 0 setAppleToRandomPosition procedureName?(apple, body arguments?) ' call procedure 1 Else 2 body.removeAt procedureName?(0 arguments?) ' call procedure 3 End If
+if (head == apple condition?) { 0 setAppleToRandomPosition procedureName?(apple, body arguments?); // call procedure 1 } else {2 body.removeAt procedureName?(0 arguments?); // call procedure 3 } // if

● Choice between an equality, a Boolean and the alternative:

+main 1 variable result name? set to false value or expression?2 +if item.equals(value)condition? then 3 reassign result variableName? to true value or expression?4 elif item.isBefore(value)condition? then 5 reassign result variableName? to binarySearch(li.subList(0, mid), item)value or expression?6 else 7 reassign result variableName? to binarySearch(li.subList(mid + 1, li.length()), item)value or expression?8 end if end main
+def main() -> None: 1 result name? = False value or expression? # variable definition 2 +if item.equals(value)condition?: 3 result variableName? = True value or expression? # reassign variable 4 elif item.isBefore(value)condition?: # else if 5 result variableName? = binarySearch(li.subList(0, mid), item)value or expression? # reassign variable 6 else:7 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression? # reassign variable 8 main()
+static void main() { 1 var result name? = false value or expression?;2 +if (item.equals(value)condition?) { 3 result variableName? = true value or expression?; // reassign variable 4 } else if (item.isBefore(value)condition?) {5 result variableName? = binarySearch(li.subList(0, mid), item)value or expression?; // reassign variable 6 } else {7 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression?; // reassign variable 8 } // if } // main
+Sub main() 1 Dim result name? = False value or expression? ' variable definition 2 +If item.equals(value)condition? Then 3 result variableName? = True value or expression? ' reassign variable 4 ElseIf item.isBefore(value)condition? Then 5 result variableName? = binarySearch(li.subList(0, mid), item)value or expression? ' reassign variable 6 Else 7 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression? ' reassign variable 8 End If End Sub
+static void main() { 1 var result name? = false value or expression?;2 +if (item.equals(value)condition?) { 3 result variableName? = true value or expression?; // reassign variable 4 } else if (item.isBefore(value)condition?) {5 result variableName? = binarySearch(li.subList(0, mid), item)value or expression?; // reassign variable 6 } else {7 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression?; // reassign variable 8 } // if } // main

## while loop

The while loop construct provides a conditional loop, used when you want execution of the enclosed instructions to begin only if some condition is true.

The condition is either a `BooleanboolboolBooleanbool` variable or an expression that evaluates to a `BooleanboolboolBooleanbool` value.

The value of the condition must a some point become false otherwise the loop will not terminate and exit.

While the condition is true the enclosed code is executed; when false the loop is bypassed. For example:

+main 1 variable file name? set to openFileForReading()value or expression?2 +while not file.endOfFile()condition? 3 call print procedureName?(file.readLine()arguments?)4 end while call file.close procedureName?(arguments?)5 end main
+def main() -> None: 1 file name? = openFileForReading()value or expression? # variable definition 2 +while not file.endOfFile()condition?: 3 print procedureName?(file.readLine()arguments?)4 file.close procedureName?(arguments?) # call procedure 5 main()
+static void main() { 1 var file name? = openFileForReading()value or expression?;2 +while (!file.endOfFile()condition?) { 3 print procedureName?(file.readLine()arguments?);4 } // while file.close procedureName?(arguments?); // call procedure 5 } // main
+Sub main() 1 Dim file name? = openFileForReading()value or expression? ' variable definition 2 +While Not file.endOfFile()condition? 3 print procedureName?(file.readLine()arguments?)4 End While file.close procedureName?(arguments?) ' call procedure 5 End Sub
+static void main() { 1 var file name? = openFileForReading()value or expression?;2 +while (!file.endOfFile()condition?) { 3 print procedureName?(file.readLine()arguments?);4 } // while file.close procedureName?(arguments?); // call procedure 5 } // main

## for loop

The construct

+for p item? in q source? 0 new code end for
+for p item? in q source?: 0 new code
+foreach (p item? in q source?) { 0 new code } // foreach
+For Each p item? In q source? 0 new code Next p
+foreach (p item? in q source?) { 0 new code } // foreach
specifies looping through a sequence either of characters in a `StringstrstringStringString`, or of items in a `ListlistListListList`.

The loop variable p does not have to have been previously declared or initialised.

#### Examples using the for loop

● The loop variable n is of the Type of a List's items (here `IntintintIntegerint`), and each integer in the List primes is in turn put into n:

+procedure printPrimes name?(parameter definitions parameter definitions?) 1 variable primes name? set to [2, 3, 5, 7, 11]value or expression?2 +for n item? in primes source? 3 call print procedureName?(n arguments?)4 end for end procedure
+def printPrimes name?(parameter definitions parameter definitions?) -> None: # procedure 1 primes name? = [2, 3, 5, 7, 11]value or expression? # variable definition 2 +for n item? in primes source?: 3 print procedureName?(n arguments?)4
+static void printPrimes name?(parameter definitions parameter definitions?) { // procedure 1 var primes name? = [2, 3, 5, 7, 11]value or expression?;2 +foreach (n item? in primes source?) { 3 print procedureName?(n arguments?);4 } // foreach } // procedure
+Sub printPrimes name?(parameter definitions parameter definitions?) ' procedure 1 Dim primes name? = {2, 3, 5, 7, 11}value or expression? ' variable definition 2 +For Each n item? In primes source? 3 print procedureName?(n arguments?)4 Next n End Sub
+static void printPrimes name?(parameter definitions parameter definitions?) { // procedure 1 var primes name? = [2, 3, 5, 7, 11]value or expression?;2 +foreach (n item? in primes source?) { 3 print procedureName?(n arguments?);4 } // foreach } // procedure

● The loop variable fruit is of the Type of a List's items (here `StringstrstringStringString`). and each String in the List basket is in turn put into fruit:

+main 1 variable basket name? set to ["apple", "banana", "cherry", "date"]value or expression?2 +for fruit item? in basket source? 3 call print procedureName?(fruit arguments?)4 end for end main
+def main() -> None: 1 basket name? = ["apple", "banana", "cherry", "date"]value or expression? # variable definition 2 +for fruit item? in basket source?: 3 print procedureName?(fruit arguments?)4 main()
+static void main() { 1 var basket name? = ["apple", "banana", "cherry", "date"]value or expression?;2 +foreach (fruit item? in basket source?) { 3 print procedureName?(fruit arguments?);4 } // foreach } // main
+Sub main() 1 Dim basket name? = {"apple", "banana", "cherry", "date"}value or expression? ' variable definition 2 +For Each fruit item? In basket source? 3 print procedureName?(fruit arguments?)4 Next fruit End Sub
+static void main() { 1 var basket name? = ["apple", "banana", "cherry", "date"]value or expression?;2 +foreach (fruit item? in basket source?) { 3 print procedureName?(fruit arguments?);4 } // foreach } // main

● To print first the keys and then the values from a `DictionaryDictionaryDictionaryDictionaryDictionary`:

+main 1 variable di name? set to ["A":1, "B":2, "C":3]value or expression?2 +for s item? in di.keys()source? 3 call print procedureName?(s arguments?)4 end for +for n item? in di.values()source? 5 call print procedureName?(n arguments?)6 end for end main
+def main() -> None: 1 di name? = ["A":1, "B":2, "C":3]value or expression? # variable definition 2 +for s item? in di.keys()source?: 3 print procedureName?(s arguments?)4 +for n item? in di.values()source?: 5 print procedureName?(n arguments?)6 main()
+static void main() { 1 var di name? = ["A":1, "B":2, "C":3]value or expression?;2 +foreach (s item? in di.keys()source?) { 3 print procedureName?(s arguments?);4 } // foreach +foreach (n item? in di.values()source?) { 5 print procedureName?(n arguments?);6 } // foreach } // main
+Sub main() 1 Dim di name? = ["A":1, "B":2, "C":3]value or expression? ' variable definition 2 +For Each s item? In di.keys()source? 3 print procedureName?(s arguments?)4 Next s +For Each n item? In di.values()source? 5 print procedureName?(n arguments?)6 Next n End Sub
+static void main() { 1 var di name? = ["A":1, "B":2, "C":3]value or expression?;2 +foreach (s item? in di.keys()source?) { 3 print procedureName?(s arguments?);4 } // foreach +foreach (n item? in di.values()source?) { 5 print procedureName?(n arguments?);6 } // foreach } // main

● Function to reverse a `StringstrstringStringString`:

+main 1 call print procedureName?(reverse("stressed")arguments?)2 end main +function reverse name?(s as String parameter definitions?) returns String Type? 3 variable sReturn name? set to ""value or expression?4 +for ch item? in s source? 5 reassign sReturn variableName? to ch + sReturn value or expression?6 end for return sReturn value or expression?7 end function
+def main() -> None: 1 print procedureName?(reverse("stressed")arguments?)2 +def reverse name?(s: str parameter definitions?) -> str Type?: # function 3 sReturn name? = ""value or expression? # variable definition 4 +for ch item? in s source?: 5 sReturn variableName? = ch + sReturn value or expression? # reassign variable 6 return sReturn value or expression?7 main()
+static void main() { 1 print procedureName?(reverse("stressed")arguments?);2 } // main +static string Type? reverse name?(string s parameter definitions?) { // function 3 var sReturn name? = ""value or expression?;4 +foreach (ch item? in s source?) { 5 sReturn variableName? = ch + sReturn value or expression?; // reassign variable 6 } // foreach return sReturn value or expression?;7 } // function
+Sub main() 1 print procedureName?(reverse("stressed")arguments?)2 End Sub +Function reverse name?(s As String parameter definitions?) As String Type? 3 Dim sReturn name? = ""value or expression? ' variable definition 4 +For Each ch item? In s source? 5 sReturn variableName? = ch + sReturn value or expression? ' reassign variable 6 Next ch Return sReturn value or expression?7 End Function
+static void main() { 1 print procedureName?(reverse("stressed")arguments?);2 } // main +static String Type? reverse name?(String s parameter definitions?) { // function 3 var sReturn name? = ""value or expression?;4 +foreach (ch item? in s source?) { 5 sReturn variableName? = ch + sReturn value or expression?; // reassign variable 6 } // foreach return sReturn value or expression?;7 } // function

● Alternatively the loop variable may be defined as an integer range using methods range  and rangeInSteps  in order to index into a subject List:

+main 1 variable numbers name? set to ["zero", "one", "two", "three", "four", "five", "six"]value or expression?2 +for n item? in range(2, 6)source? 3 call print procedureName?(numbers[n]arguments?)4 end for end main
+def main() -> None: 1 numbers name? = ["zero", "one", "two", "three", "four", "five", "six"]value or expression? # variable definition 2 +for n item? in range(2, 6)source?: 3 print procedureName?(numbers[n]arguments?)4 main()
+static void main() { 1 var numbers name? = ["zero", "one", "two", "three", "four", "five", "six"]value or expression?;2 +foreach (n item? in range(2, 6)source?) { 3 print procedureName?(numbers[n]arguments?);4 } // foreach } // main
+Sub main() 1 Dim numbers name? = {"zero", "one", "two", "three", "four", "five", "six"}value or expression? ' variable definition 2 +For Each n item? In range(2, 6)source? 3 print procedureName?(numbers[n]arguments?)4 Next n End Sub
+static void main() { 1 var numbers name? = ["zero", "one", "two", "three", "four", "five", "six"]value or expression?;2 +foreach (n item? in range(2, 6)source?) { 3 print procedureName?(numbers[n]arguments?);4 } // foreach } // main

#### Technical note about the for loop variable

● The for instruction creates its own working copy of the values through which to loop sequentially. So even if the loop variable is changed in any way within the for loop, this will not affect which subject items are referred to.

It is therefore recommended never to reassign the loop variable within the loop.

## call procedure

The call procedure instruction is used when you want to run a procedure .

The procedure may be:

- a procedure that you have defined at the global level
  `call fillRandomprocedureName?(gridarguments?)0fillRandomprocedureName?(gridarguments?) # call procedure0fillRandomprocedureName?(gridarguments?); // call procedure0fillRandomprocedureName?(gridarguments?) ' call procedure0fillRandomprocedureName?(gridarguments?); // call procedure0`
- a procedure method on an object of a class that you have defined
  `call apple.newRandomPositionprocedureName?(snakearguments?)0apple.newRandomPositionprocedureName?(snakearguments?) # call procedure0apple.newRandomPositionprocedureName?(snakearguments?); // call procedure0apple.newRandomPositionprocedureName?(snakearguments?) ' call procedure0apple.newRandomPositionprocedureName?(snakearguments?); // call procedure0`
- a procedure method that belongs to the same class as the procedure that you are calling from
  `call updateNeighboursprocedureName?(arguments?)0updateNeighboursprocedureName?(arguments?) # call procedure0updateNeighboursprocedureName?(arguments?); // call procedure0updateNeighboursprocedureName?(arguments?) ' call procedure0updateNeighboursprocedureName?(arguments?); // call procedure0`
- a procedure provided by the standard library
  `call sleep_msprocedureName?(2000arguments?)0sleep_msprocedureName?(2000arguments?) # call procedure0sleep_msprocedureName?(2000arguments?); // call procedure0sleep_msprocedureName?(2000arguments?) ' call procedure0sleep_msprocedureName?(2000arguments?); // call procedure0`
- a procedure method on an object of a Type provided by the standard library
  `call vg.appendprocedureName?(rectarguments?)0vg.appendprocedureName?(rectarguments?) # call procedure0vg.appendprocedureName?(rectarguments?); // call procedure0vg.appendprocedureName?(rectarguments?) ' call procedure0vg.appendprocedureName?(rectarguments?); // call procedure0`

The arguments provided must match the number and Type of the parameters specified in the definition of the procedure. If there are no parameters, leave the brackets empty.

An argument whose value is changed by the procedure must be:

- either a mutable data structure (List or Dictionary)
- or a Ref reference to a named value Type
- or a Ref reference to an immutable data structure (Set, Stack or Queue)

For procedures that you define yourself, any argument whose value is changed must be of a mutable Type.

An expression of the correct Type can be used as an argument, but its value cannot be changed in the procedure.

Procedures may have side effects, for example input/output or changing a data value in an object. They can change the contents of any mutable object passed in as an argument. For this reason, procedures cannot be called from functions, which are not allowed to have side effects. To enforce this, call procedure instructions are not allowed in functions.

There is a limit to the complexity of a call procedure instruction. Only one dot is allowed in the procedure name field, or two dots if the first word is property. If you need anything more complicated, use a change variable instruction on the line above. See the error message explanation for 'procedureName' in a call instruction .

## try

You can enclose code in a try construction when you want it to be able, at execution, to throw an exception that you handle.

This might arise when calling a System method  that is dependent upon external conditions, such as when cancelling the writing of a text file, as in the example in Writing text files .

The try construction automatically provides a catch clause in which you provide a String for an message.

You can also use a test to check whether another piece of code might throw an exception by wrapping it in a try instruction.

#### Examples using try

● To check a function input, and throw an exception up:

+main 1 +try 2 variable t name? set to foo(true)value or expression?3 call print procedureName?("no error"arguments?)4 catch err variableName? as CustomError type e.g. ElanRuntimeError or CustomError?5 call print procedureName?(err arguments?)6 end try end main +function foo name?(torf as Boolean parameter definitions?) returns Boolean Type? 7 +if torf condition? then 8 throw CustomError exception type? "error in foo()"message?9 end if return torf value or expression?10 end function
+def main() -> None: 1 +try: 2 t name? = foo(True)value or expression? # variable definition 3 print procedureName?("no error"arguments?)4 except CustomError type e.g. ElanRuntimeError or CustomError? as err variableName?: # catch 5 print procedureName?(err arguments?)6 +def foo name?(torf: bool parameter definitions?) -> bool Type?: # function 7 +if torf condition?: 8 raise CustomError exception type?("error in foo()"message?)9 return torf value or expression?10 main()
+static void main() { 1 +try { 2 var t name? = foo(true)value or expression?;3 print procedureName?("no error"arguments?);4 } catch (CustomError type e.g. ElanRuntimeError or CustomError? err variableName?) {5 print procedureName?(err arguments?);6 } // try } // main +static bool Type? foo name?(bool torf parameter definitions?) { // function 7 +if (torf condition?) { 8 throw new CustomError exception type?("error in foo()"message?);9 } // if return torf value or expression?;10 } // function
+Sub main() 1 +Try 2 Dim t name? = foo(True)value or expression? ' variable definition 3 print procedureName?("no error"arguments?)4 Catch err variableName? As CustomError type e.g. ElanRuntimeError or CustomError?5 print procedureName?(err arguments?)6 End Try End Sub +Function foo name?(torf As Boolean parameter definitions?) As Boolean Type? 7 +If torf condition? Then 8 Throw New CustomError exception type?("error in foo()"message?)9 End If Return torf value or expression?10 End Function
+static void main() { 1 +try { 2 var t name? = foo(true)value or expression?;3 print procedureName?("no error"arguments?);4 } catch (CustomError type e.g. ElanRuntimeError or CustomError? err variableName?) {5 print procedureName?(err arguments?);6 } // try } // main +static bool Type? foo name?(bool torf parameter definitions?) { // function 7 +if (torf condition?) { 8 throw new CustomError exception type?("error in foo()"message?);9 } // if return torf value or expression?;10 } // function

When foo is given argument true, output is "error in foo()"; when given false, output is "no error".

● To stop the program if one of two points (each a Tuple) has negative x or y:

+main 1 variable a name? set to (1.0, 2.0)value or expression?2 variable b name? set to (3.0, -6.0)value or expression?3 variable fQ name? set to firstQuadrant(a, b)value or expression?4 end main +function firstQuadrant name?(a as (Float, Float), b as (Float, Float)parameter definitions?) returns Float Type? 5 +if (a.item_0 < 0) or (a.item_1 < 0) or (b.item_0 < 0) or (b.item_1 < 0)condition? then 6 throw CustomError exception type? $"point {a} or (b} is not in the first quadrant"message?7 end if return 0 value or expression?8 end function
+def main() -> None: 1 a name? = (1.0, 2.0)value or expression? # variable definition 2 b name? = (3.0, -6.0)value or expression? # variable definition 3 fQ name? = firstQuadrant(a, b)value or expression? # variable definition 4 +def firstQuadrant name?(a: tuple[float, float], b: tuple[float, float]parameter definitions?) -> float Type?: # function 5 +if (a.item_0 < 0) or (a.item_1 < 0) or (b.item_0 < 0) or (b.item_1 < 0)condition?: 6 raise CustomError exception type?(f"point {a} or (b} is not in the first quadrant"message?)7 return 0 value or expression?8 main()
+static void main() { 1 var a name? = (1.0, 2.0)value or expression?;2 var b name? = (3.0, -6.0)value or expression?;3 var fQ name? = firstQuadrant(a, b)value or expression?;4 } // main +static double Type? firstQuadrant name?((double, double) a, (double, double) b parameter definitions?) { // function 5 +if ((a.item_0 < 0) || (a.item_1 < 0) || (b.item_0 < 0) || (b.item_1 < 0)condition?) { 6 throw new CustomError exception type?($"point {a} or (b} is not in the first quadrant"message?);7 } // if return 0 value or expression?;8 } // function
+Sub main() 1 Dim a name? = (1.0, 2.0)value or expression? ' variable definition 2 Dim b name? = (3.0, -6.0)value or expression? ' variable definition 3 Dim fQ name? = firstQuadrant(a, b)value or expression? ' variable definition 4 End Sub +Function firstQuadrant name?(a As (Double, Double), b As (Double, Double)parameter definitions?) As Double Type? 5 +If (a.item_0 < 0) Or (a.item_1 < 0) Or (b.item_0 < 0) Or (b.item_1 < 0)condition? Then 6 Throw New CustomError exception type?($"point {a} or (b} is not in the first quadrant"message?)7 End If Return 0 value or expression?8 End Function
+static void main() { 1 var a name? = (1.0, 2.0)value or expression?;2 var b name? = (3.0, -6.0)value or expression?;3 var fQ name? = firstQuadrant(a, b)value or expression?;4 } // main +static double Type? firstQuadrant name?((double, double) a, (double, double) b parameter definitions?) { // function 5 +if ((a.item_0 < 0) || (a.item_1 < 0) || (b.item_0 < 0) || (b.item_1 < 0)condition?) { 6 throw new CustomError exception type?(String.format("point % or (b} is not in the first quadrant", a)message?);7 } // if return 0 value or expression?;8 } // function

## throw

You can deliberately generate, or 'throw', an error exception when a specific circumstance is identified, using a throw instruction which defines an explanatory string.

For the program to retain control when an exception is raised, use the try  instruction.

#### Example using throw exception

● To stop the program if a value calculated in a function is out of range:

+main 1 call print procedureName?($"{percent(23, 20)}" + "%"arguments?)2 end main +function percent name?(value as Float, maximum as Float parameter definitions?) returns Float Type? 3 +if value > maximum condition? then 4 throw ElanRuntimeError exception type? "proportion exceeds 100%"message?5 end if return value/maximum*100 value or expression?6 end function
+def main() -> None: 1 print procedureName?(f"{percent(23, 20)}" + "%"arguments?)2 +def percent name?(value: float, maximum: float parameter definitions?) -> float Type?: # function 3 +if value > maximum condition?: 4 raise ElanRuntimeError exception type?("proportion exceeds 100%"message?)5 return value/maximum*100 value or expression?6 main()
+static void main() { 1 print procedureName?($"{percent(23, 20)}" + "%"arguments?);2 } // main +static double Type? percent name?(double value, double maximum parameter definitions?) { // function 3 +if (value > maximum condition?) { 4 throw new ElanRuntimeError exception type?("proportion exceeds 100%"message?);5 } // if return value/maximum*100 value or expression?;6 } // function
+Sub main() 1 print procedureName?($"{percent(23, 20)}" + "%"arguments?)2 End Sub +Function percent name?(value As Double, maximum As Double parameter definitions?) As Double Type? 3 +If value > maximum condition? Then 4 Throw New ElanRuntimeError exception type?("proportion exceeds 100%"message?)5 End If Return value/maximum*100 value or expression?6 End Function
+static void main() { 1 print procedureName?(String.format arguments?);2 } // main +static double Type? percent name?(double value, double maximum parameter definitions?) { // function 3 +if (value > maximum condition?) { 4 throw new ElanRuntimeError exception type?("proportion exceeds 100%"message?);5 } // if return value/maximum*100 value or expression?;6 } // function

At runtime, if the condition is met, execution will stop and the display will show:

        proportion exceeds 100%
        Error

## assert

The assert equal instruction is used only within a test , which is the mechanism for running unit tests during program development, not during program execution.

Some programming languages have a feature for making assertions while your program is running. In Elan, you can get equivalent functionality by throwing an exception, as described in the throw exception  instruction.

## let statement

Of use only in `testtesttesttesttest` instructions and in Functional Programming functions `letletletletlet` is used to define constant values defined by expressions (or literals).

The let statement instruction declares and initialises an immutable named value whose scope is confined to the function.

The name defined must be a valid identifier .

You can declare a such a constant within a loop, so that the named value gets a new value each time it is executed, but its value cannot be changed in any other way.

Unlike a global constant , the value assigned in a let statement may be any value, literal or expression:

+function numbers name?(parameter definitions parameter definitions?) returns (Float, Float)Type? 1 let tau name? be 2*pi value or expression?2 let phi name? be (1 + sqrt(5))/2 value or expression?3 return (tau, phi)value or expression?4 end function
+def numbers name?(parameter definitions parameter definitions?) -> tuple[float, float]Type?: # function 1 tau name? = 2*pi value or expression? # let 2 phi name? = (1 + sqrt(5))/2 value or expression? # let 3 return (tau, phi)value or expression?4
+static (double, double)Type? numbers name?(parameter definitions parameter definitions?) { // function 1 var tau name? = 2*pi value or expression?; // let 2 var phi name? = (1 + sqrt(5))/2 value or expression?; // let 3 return (tau, phi)value or expression?;4 } // function
+Function numbers name?(parameter definitions parameter definitions?) As (Double, Double)Type? 1 Dim tau name? = 2*pi value or expression? ' let 2 Dim phi name? = (1 + sqrt(5))/2 value or expression? ' let 3 Return (tau, phi)value or expression?4 End Function
+static (double, double)Type? numbers name?(parameter definitions parameter definitions?) { // function 1 var tau name? = 2*pi value or expression?; // let 2 var phi name? = (1 + sqrt(5))/2 value or expression?; // let 3 return (tau, phi)value or expression?;4 } // function

# Expressions

One of the most important constructs in programming is the expression. An expression evaluates and returns a value using the following elements:

- Literal value 
- Named value 
- Operator  (including round brackets)
- function reference 
- lambda 

## Literal value

A literal value is where a value is written 'literally' in the code, such as `3.1423.1423.1423.1423.142`, in contrast to a value that is referred to by a name.

Here is a table showing some example literal values. Follow the links for more information about each Type.

Type | Example of literal
--- | ---
Int  | `33333`
Float  | `2.02.02.02.02.0`
Boolean  | true
String  | `"Hello""Hello""Hello""Hello""Hello"`
Tuple  | `(3, "banana")(3, "banana")(3, "banana")(3, "banana")(3, "banana")`
List  | `["lemon", "lime", "orange"]["lemon", "lime", "orange"]["lemon", "lime", "orange"]{"lemon", "lime", "orange"}["lemon", "lime", "orange"]`
Dictionary  | `["a":3, "b":5]["a":3, "b":5]["a":3, "b":5]["a":3, "b":5]["a":3, "b":5]`

For more about List and Dictionary literals see the Standard data structures  table.

## Indexed values

If a named value is of an indexable Type (`StringstrstringStringString` or `ListlistListListList`), then you can refer to a contiguous subset (or range) of its values using methods subString and subList respectively.

The upper index of a range is exclusive, so to define a range that picks items indexed from i to j, you would specify the range as `(i, j + 1)(i, j + 1)(i, j + 1)(i, j + 1)(i, j + 1)`.

If the two index values of a range are equal, or the second is smaller than the first, then an empty string or list is returned.

Indexes are used only for reading values. Writing a value to a specific index location in a list is done using method put .

Example using indexing on a string:

+main 1 variable a name? set to "Hello world!"value or expression?2 call print procedureName?(a[4]arguments?)3 call print procedureName?(a.subString(4, a.length())arguments?)4 call print procedureName?(a.subString(0, 7)arguments?)5 end main +def main() -> None: 1 a name? = "Hello world!"value or expression? # variable definition 2 print procedureName?(a[4]arguments?)3 print procedureName?(a.subString(4, a.length())arguments?)4 print procedureName?(a.subString(0, 7)arguments?)5 main() +static void main() { 1 var a name? = "Hello world!"value or expression?;2 print procedureName?(a[4]arguments?);3 print procedureName?(a.subString(4, a.length())arguments?);4 print procedureName?(a.subString(0, 7)arguments?);5 } // main +Sub main() 1 Dim a name? = "Hello world!"value or expression? ' variable definition 2 print procedureName?(a[4]arguments?)3 print procedureName?(a.subString(4, a.length())arguments?)4 print procedureName?(a.subString(0, 7)arguments?)5 End Sub +static void main() { 1 var a name? = "Hello world!"value or expression?;2 print procedureName?(a[4]arguments?);3 print procedureName?(a.subString(4, a.length())arguments?);4 print procedureName?(a.subString(0, 7)arguments?);5 } // main | ⟶ ⟶ ⟶ | o o world! Hello w (since the upper bound of a range is exclusive)

And on a list:

+main 1 variable li name? set to new List<of Int>()value or expression?2 reassign li variableName? to [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]value or expression?3 call print procedureName?(li[4]arguments?)4 call print procedureName?(li.subList(4, li.length())arguments?)5 call print procedureName?(li.subList(0, 7)arguments?)6 end main +def main() -> None: 1 li name? = list[int]()value or expression? # variable definition 2 li variableName? = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]value or expression? # reassign variable 3 print procedureName?(li[4]arguments?)4 print procedureName?(li.subList(4, li.length())arguments?)5 print procedureName?(li.subList(0, 7)arguments?)6 main() +static void main() { 1 var li name? = new List<int>()value or expression?;2 li variableName? = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]value or expression?; // reassign variable 3 print procedureName?(li[4]arguments?);4 print procedureName?(li.subList(4, li.length())arguments?);5 print procedureName?(li.subList(0, 7)arguments?);6 } // main +Sub main() 1 Dim li name? = New List(Of Integer)()value or expression? ' variable definition 2 li variableName? = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}value or expression? ' reassign variable 3 print procedureName?(li[4]arguments?)4 print procedureName?(li.subList(4, li.length())arguments?)5 print procedureName?(li.subList(0, 7)arguments?)6 End Sub +static void main() { 1 var li name? = new List<int>()value or expression?;2 li variableName? = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]value or expression?; // reassign variable 3 print procedureName?(li[4]arguments?);4 print procedureName?(li.subList(4, li.length())arguments?);5 print procedureName?(li.subList(0, 7)arguments?);6 } // main | ⟶ ⟶ ⟶ | 4 (the value of the list item) [4, 5, 6, 7, 8, 9, 10, 11] (a new list) [0, 1, 2, 3, 4, 5, 6] (since the upper bound of a range is exclusive)

## Operators

### Arithmetic operators

Arithmetic operators can be applied to `FloatfloatdoubleDoubledouble` or `IntintintIntegerint` arguments. The result may be a `FloatfloatdoubleDoubledouble` or an `IntintintIntegerint` depending on the arguments.

For the + − * operators, the result is a `FloatfloatdoubleDoubledouble` if either of the arguments is a `FloatfloatdoubleDoubledouble`, and an `IntintintIntegerint` if both arguments are `IntintintIntegerint`.

For the / operator, at least one of the values must be a `FloatfloatdoubleDoubledouble`, and the result is always a `FloatfloatdoubleDoubledouble`. It can be converted to an `IntintintIntegerint` using standalone function floor .

For raising one value to the power of another, use the syntax in these examples:

`call printprocedureName?(pow(4, 4)arguments?)0printprocedureName?(pow(4, 4)arguments?)0printprocedureName?(pow(4, 4)arguments?);0printprocedureName?(pow(4, 4)arguments?)0printprocedureName?(pow(4, 4)arguments?);0`
`variable cname? set to sqrt(pow(a, 2) + pow(b, 2))value or expression?0cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression? # variable definition0var cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression?;0Dim cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression? ' variable definition0var cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression?;0`

If, when including a power in an expression, it does not parse, try enclosing parts of the expression in brackets to remove potential ambiguity.

The operator mod (integer remainder) is applied only to `IntintintIntegerint` arguments, and the result is `IntintintIntegerint`.

`2/3.02/3.02/3.02/3.02/3.0` | ⟶ | 0.666..
`2*32*32*32*32*3` | ⟶ | 6
`2 + 32 + 32 + 32 + 32 + 3` | ⟶ | 5
`2 - 32 - 32 - 32 - 32 - 3` | ⟶ | −1
`11 mod 311 % 311 % 311 Mod 311 % 3` | ⟶ | 2

For integer division, either use method floor on a `FloatfloatdoubleDoubledouble` result, or use method divAsInt on `FloatfloatdoubleDoubledouble` arguments (which returns an `IntintintIntegerint`):

`(11.0/3.0).floor()(11.0/3.0).floor()(11.0/3.0).floor()(11.0/3.0).floor()(11.0/3.0).floor()` | ⟶ | 3
`(-11.0/3.0).floor()(-11.0/3.0).floor()(-11.0/3.0).floor()(-11.0/3.0).floor()(-11.0/3.0).floor()` | ⟶ | −4
`divAsInt(11.0, 3.0)divAsInt(11.0, 3.0)divAsInt(11.0, 3.0)divAsInt(11.0, 3.0)divAsInt(11.0, 3.0)` | ⟶ | 3

Note that rounding is always down.

Arithmetic operators follow the conventional rules for precedence i.e. 'BIDMAS' (or 'BODMAS').

When combining mod with other operators in an expression, insert round brackets to avoid ambiguity e.g.:

`(5 + 6) mod 3(5 + 6) % 3(5 + 6) % 3(5 + 6) Mod 3(5 + 6) % 3` | ⟶ | 2

Note that mod is more of a remainder operator than a modulus operator. The result takes the sign of the first argument. If both arguments are positive, there is no difference.

The minus sign may also be used as a unary operator, and this takes precedence over binary operators so:

`2*-32*-32*-32*-32*-3` | ⟶ | −6

The editor automatically puts spaces around the operators + and −, but not around / or *. This is just to visually reinforce the precedence.

### Logical operators

Logical operators are applied to `BooleanboolboolBooleanbool` arguments and return a `BooleanboolboolBooleanbool` result.

`andandandandand` and `ororororor` are binary operators
`notnotnotnotnot` is a unary operator.

The operator precedence is `notnotnotnotnot` → `andandandandand` → `ororororor`, so this example, which implements an 'exclusive or', need not use brackets and can rely on the operator precedence:

+function exOr name?(a as Boolean, b as Boolean parameter definitions?) returns Boolean Type? 1 return a and not b or b and not a value or expression?2 end function
+def exOr name?(a: bool, b: bool parameter definitions?) -> bool Type?: # function 1 return a and not b or b and not a value or expression?2
+static bool Type? exOr name?(bool a, bool b parameter definitions?) { // function 1 return a && !b || b && !a value or expression?;2 } // function
+Function exOr name?(a As Boolean, b As Boolean parameter definitions?) As Boolean Type? 1 Return a And Not b Or b And Not a value or expression?2 End Function
+static bool Type? exOr name?(bool a, bool b parameter definitions?) { // function 1 return a && !b || b && !a value or expression?;2 } // function

### String operator

The + operator is also used for concatenating `StringstrstringStringString` values.

### Equality testing

#### Testing equality of `IntintintIntegerint`, `FloatfloatdoubleDoubledouble` or `BooleanboolboolBooleanbool` values

Equality testing of these Value Types uses the is and isnt operators between two values and returns a `BooleanboolboolBooleanbool` result:

- isnt returns the opposite of is.
- `(a is b)(a == b)(a == b)(a = b)(a == b)` returns true, if a and b are both of the same Type and their values are equal. The only exception is that if one argument is of Type `FloatfloatdoubleDoubledouble` and the other is of Type `IntintintIntegerint`, then is will return true (and isnt will return false) if their values are the same, i.e. they are the same whole number.
- It is also possible to use methods equals and notEqualTo described below.

#### Testing equality of `StringstrstringStringString` values and of all Reference Types

Equality testing of these Reference Types uses common dot methods  equals and notEqualTo:

- +if listA.equals(listB)condition? then 0 new code end if
  +if listA.equals(listB)condition?: 0 new code
  +if (listA.equals(listB)condition?) { 0 new code } // if
  +If listA.equals(listB)condition? Then 0 new code End If
  +if (listA.equals(listB)condition?) { 0 new code } // if
- `reassign differsvariableName? to set1.notEqualTo(set2)value or expression?0differsvariableName? = set1.notEqualTo(set2)value or expression? # reassign variable0differsvariableName? = set1.notEqualTo(set2)value or expression?; // reassign variable0differsvariableName? = set1.notEqualTo(set2)value or expression? ' reassign variable0differsvariableName? = set1.notEqualTo(set2)value or expression?; // reassign variable0`

The comparison is made sequentially through the characters or items in the structures to see if the objects are equal. Two Lists compare equal if they contain the same items in the same order. And two instances of the same class compare equal if the values of all their properties compare equal.

The compiler rejects any attempt to compare instances of different classes unless abstract classes and inheritance are involved. Two instances which are subclasses of the same abstract class compare equal only if they are of the same class (and have the same property values).

### Numeric comparison

The numeric comparison operators are:

> | for | greater than
< | for | less than
>= | for | greater than or equal to
<= | for | less than or equal to

Each may be applied between two values of Type `FloatfloatdoubleDoubledouble`, but any named value or expression that evaluates to an `IntintintIntegerint` may always be used where a `FloatfloatdoubleDoubledouble` is expected.

These operators cannot be applied to strings. Use the dot methods isBefore and isAfter to compare strings alphabetically. See Dot methods on a String .

### Combining operators

You can combine operators of different kinds, e.g. combining numeric comparison with logical operators in a single expression. However the rules of precedence between operators of different kinds are complex. It is strongly recommend that you always use brackets to disambiguate such expressions, for example:

`reassign xvariableName? to (a > b) and (b < c)value or expression?0xvariableName? = (a > b) and (b < c)value or expression? # reassign variable0xvariableName? = (a > b) && (b < c)value or expression?; // reassign variable0xvariableName? = (a > b) And (b < c)value or expression? ' reassign variable0xvariableName? = (a > b) && (b < c)value or expression?; // reassign variable0`
`reassign xvariableName? to (a + b) > (c - d)value or expression?0xvariableName? = (a + b) > (c - d)value or expression? # reassign variable0xvariableName? = (a + b) > (c - d)value or expression?; // reassign variable0xvariableName? = (a + b) > (c - d)value or expression? ' reassign variable0xvariableName? = (a + b) > (c - d)value or expression?; // reassign variable0`

## Function reference

An expression may simply be a reference to a function, or it may include several function references within it. Examples:
+main 1 call print procedureName?(sin(radians(30))arguments?)2 variable x name? set to pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression?3 variable name name? set to input("Your name")value or expression?4 call print procedureName?(name.upperCase()arguments?)5 end main
+def main() -> None: 1 print procedureName?(sin(radians(30))arguments?)2 x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression? # variable definition 3 name name? = input("Your name")value or expression? # variable definition 4 print procedureName?(name.upperCase()arguments?)5 main()
+static void main() { 1 print procedureName?(sin(radians(30))arguments?);2 var x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression?;3 var name name? = input("Your name")value or expression?;4 print procedureName?(name.upperCase()arguments?);5 } // main
+Sub main() 1 print procedureName?(sin(radians(30))arguments?)2 Dim x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression? ' variable definition 3 Dim name name? = input("Your name")value or expression? ' variable definition 4 print procedureName?(name.upperCase()arguments?)5 End Sub
+static void main() { 1 print procedureName?(sin(radians(30))arguments?);2 var x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression?;3 var name name? = input("Your name")value or expression?;4 print procedureName?(name.upperCase()arguments?);5 } // main

#### Notes

- The third example above is not strictly a function call, but is a 'system method' call. System methods may be used only within the main routine or a procedure, because they have external dependencies or side effects.
- In the fourth example, `upperCaseupperCaseupperCaseupperCaseupperCase` is a dot method that may be applied to any instance (variable or literal) of Type `StringstrstringStringString`. See Dot methods on a String .

## lambda

A lambda is a lightweight means of defining a function 'inline' and without a name (i.e. an anonymous function).

You can use a lambda only as an argument to a Higher-order Function .

You would typically define a lambda when the functionality it defines is needed in only one location, e.g. in a particular call to a Higher-order Function.

The syntax for a lambda is as follows:

- Start with the word lambda.
- Parameter definitions, comma-separated, follow the same form as parameter definitions in a function or procedure, but without surrounding brackets.
- The => symbol, which is usually articulated as 'returns', 'yields' or 'fat arrow'.
- An expression that makes use of the parameters, and may also make use of other variables that are in scope.

For examples of using lambda in Higher-order Functions, see Library functions that process Lists 

## if (expression)

The if expression returns one of two values or expressions dependent upon the evaulation of a Boolean value:

Its syntax is shown in this reassign variable instruction:

`variable isBiggername? set to if(a >= b, true, false)value or expression?0isBiggername? = if(a >= b, True, False)value or expression? # variable definition0var isBiggername? = if(a >= b, true, false)value or expression?;0Dim isBiggername? = if(a >= b, True, False)value or expression? ' variable definition0var isBiggername? = if(a >= b, true, false)value or expression?;0`

Similarly, but returning an evaluated expression:

`variable dname? set to if(c < 580, c - 40, c + 60)value or expression?0dname? = if(c < 580, c - 40, c + 60)value or expression? # variable definition0var dname? = if(c < 580, c - 40, c + 60)value or expression?;0Dim dname? = if(c < 580, c - 40, c + 60)value or expression? ' variable definition0var dname? = if(c < 580, c - 40, c + 60)value or expression?;0`

in which variable d takes the value of `c - 40c - 40c - 40c - 40c - 40` if `c < 580c < 580c < 580c < 580c < 580`, or `c + 60c + 60c + 60c + 60c + 60` otherwise.

An if expression may be used within an if expression but may be hard to read and understand.

#### Examples using if expression:

● Choice in a return instruction:

+function foo name?(parameter definitions parameter definitions?) returns Int Type? 1 return if(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?2 end function
+def foo name?(parameter definitions parameter definitions?) -> int Type?: # function 1 return if(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?2
+static int Type? foo name?(parameter definitions parameter definitions?) { // function 1 return if(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?;2 } // function
+Function foo name?(parameter definitions parameter definitions?) As Integer Type? 1 Return if(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?2 End Function
+static int Type? foo name?(parameter definitions parameter definitions?) { // function 1 return if(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?;2 } // function

● Using an if expression in a call procedure print:

+main 1 variable p name? set to unicode(0x03c0)value or expression?2 call testPi procedureName?(p, 3 arguments?)3 call testPi procedureName?(p, 4 arguments?)4 end main +procedure testPi name?(p as String, v as Float parameter definitions?) 5 call print procedureName?(if(pi > v, $"{p} > {v}", $"{p} < {v}")arguments?)6 end procedure +def main() -> None: 1 p name? = unicode(0x03c0)value or expression? # variable definition 2 testPi procedureName?(p, 3 arguments?) # call procedure 3 testPi procedureName?(p, 4 arguments?) # call procedure 4 +def testPi name?(p: str, v: float parameter definitions?) -> None: # procedure 5 print procedureName?(if(pi > v, f"{p} > {v}", f"{p} < {v}")arguments?)6 main() +static void main() { 1 var p name? = unicode(0x03c0)value or expression?;2 testPi procedureName?(p, 3 arguments?); // call procedure 3 testPi procedureName?(p, 4 arguments?); // call procedure 4 } // main +static void testPi name?(string p, double v parameter definitions?) { // procedure 5 print procedureName?(if(pi > v, $"{p} > {v}", $"{p} < {v}")arguments?);6 } // procedure +Sub main() 1 Dim p name? = unicode(&H03c0)value or expression? ' variable definition 2 testPi procedureName?(p, 3 arguments?) ' call procedure 3 testPi procedureName?(p, 4 arguments?) ' call procedure 4 End Sub +Sub testPi name?(p As String, v As Double parameter definitions?) ' procedure 5 print procedureName?(if(pi > v, $"{p} > {v}", $"{p} < {v}")arguments?)6 End Sub +static void main() { 1 var p name? = unicode(0x03c0)value or expression?;2 testPi procedureName?(p, 3 arguments?); // call procedure 3 testPi procedureName?(p, 4 arguments?); // call procedure 4 } // main +static void testPi name?(String p, double v parameter definitions?) { // procedure 5 print procedureName?(arguments?);6 } // procedure | ⟶ ⟶ | π > 3 π < 4

## new

A 'new instance' expression is used to create a new instance of a library data structure , or a user-defined class , either to assign to a named value, or as part of a more complex expression. Example of use from demo program snake_PP.elan:

`variable headRefname? set to new AsRef<of List<of Int>>(head)value or expression?0headRefname? = AsRef[list[int]](head)value or expression? # variable definition0var headRefname? = new AsRef<List<int>>(head)value or expression?;0Dim headRefname? = New AsRef(Of List(Of Integer))(head)value or expression? ' variable definition0var headRefname? = new AsRef<List<int>>(head)value or expression?;0`

# Comments

## # comment

A comment is not an instruction: it is ignored by the compiler and does not change how the program works. Rather, a comment contains information about the program, intended to be read by a person seeking to understand or modify the code.

A comment is entered at any editor prompt by typing the hash symbol # which then provides a field in which you may enter text, or leave blank. Your text may contain any characters, except that it must not start with an open square bracket [.

Comments may be inserted at any level: in the Global , Member , or Statement  instruction levels, as well as from the new code prompt. Every prompt provides a `commentcommentcommentcommentcomment` option, namely a # symbol.

Every Elan program has a single comment at the top of the file, which is generated by the system and cannot be edited or deleted by the user. This comment is known as the 'file header' and shows the version of Elan being run.

# Compile errors and warnings

Q: What is the difference between a compile error and a warning.

A: A warning usually indicates that the fix may involve adding some more code, for example adding a definition for an unknown identifier. An error usually indicates that you will need to alter code to fix the error. But they are similar in that you will not be able to run your program until the issues are fixed. In all programming languages it is a good practice 'treat all compile warnings as errors' i.e. fix them as soon as you see them appear.

## Messages

### Expression must be ...

An expression, when evaluated, results in a value of a Type that is not compatible with its 'target', for example: if the result of the expression is being assigned to an existing variable, or if an expression is defined 'inline' as an argument into a method call.

### Cannot use 'this' outside class context

`thisthisthisthisthis` may only be used within an instance method on a class to refer to the current instance.

### Abstract class ... must be declared before it is used

If a class inherits from one or more abstract classes, then the latter must all have already been declared (defined) earlier in the code file.

### Member ... must be of type ...

This error occurs when a class is defined as inheriting from an abstract class, and has implemented an inherited member (method or property) with the correct name, but with different Types.

### Incompatible types. Expected: ... Provided: ...

### Cannot determine common type between ... and ...

### ... is not defined for type ...

Arises when 'dot calling' a member (method or property) that does not exist on the Type of the named value or expression before the dot.

### Cannot call a function as a procedure

A function (or function method) is to be used within an expression, not via a call procedure instruction.

### Cannot use a system method in a function

A 'system method' (defined in the Standard Library) returns a value like a function does. However, because a system method either makes changes to the system and/or depends on external inputs, it may be used only within a procedure or the main routine.

### Code change required ...

Indicates that a library method or class has been changed since the version in which your Elan code was written. The link in the message should take you directly to information in the Library Reference documentation on how to update your code to cope with the change.

### Cannot call procedure ... within an expression

A procedure may be used only within a call procedure instruction.

### Cannot invoke ... as a method

The code is attempting to use a free-standing method (function or procedure) as a 'dot method' on a named value or the result of an expression.

### Cannot ...index ...

An index (in square brackets) may be applied only to certain data structure Types: `StringstrstringStringString`, `ListlistListListList` and `DictionaryDictionaryDictionaryDictionaryDictionary`.

### Cannot range ...

A range may be applied only to certain data structure Types: `StringstrstringStringString` and `ListlistListListList`.

### Cannot new ...

The Type specified after the call procedure instruction cannot be instantiated. Either the Type is inapplicable, or it is an abstract class or interface.

### Superclass ... must be inheritable class

A concrete class may inherit from an abstract class, and/or an interface, but not from another concrete class. In Elan, all classes must be either abstract or 'final': a final class being concrete and not-inheritable.

### Superclass ... must be an interface

An interface may inherit from other interfaces, but not from any class.

### class/interface ... cannot inherit from itself

The message is self explanatory.

### There must be only one abstract superclass ...

A class may inherit from only one abstract class. However, it may additionally inherit from one or more interfaces.

### Cannot reference private member ...

A private member (method or property) may be accessed only by code within the class, or within subclasses of it. It may not be accessed by any code outside the class hierarchy.

### ... must implement ...

If a concrete class inherits from any abstract class or interface(s) it must implement all abstract methods defined in those Types.

### ... must be concrete to new

You cannot create an instance of any abstract class or interface: only of a concrete class.

### Cannot call extension method directly

A method that is defined within the Library as an extension method, such as toString, may be called on a named value or an expression only using dot syntax .

### Cannot prefix function with 'property'

The prefix property. may only be used before a property name: not a function name.

### Missing argument(s) ...

The method being called expects more arguments than have been provided.

### Too many argument(s) ...

A method has been passed more arguments than it expects.

### Argument types ...

One or more arguments provided to the method are of the wrong Type.

### ...<of Type>...

Certain data structure Types, including `ListlistListListList`, must specify the Type of their members, for example `ListlistListListList`<of `IntintintIntegerint`>. Failure to specify the '<of Type>' on these Types will give an error, as will specifying 'of Type' where it is not required. Dictionaries require Types to be specified for both the keys and the values, for example: `DictionaryDictionaryDictionaryDictionaryDictionary`<of `StringstrstringStringString`, `FloatfloatdoubleDoubledouble`>.

### May not reassign the ...

Attempting to reassign, or mutate, a named value that may not be reassigned in the current context.

### Name ... not unique in scope ...

Attempting to create an identifier with the same name as one already defined within the same scope.

### May not set ... in a function

A property can be reassigned only within a procedure method, not within a function, because reassigning a property is a side effect.

### The identifier ... is already used for a ... and cannot be re-defined here.

An existing named value may not be defined again within the same scope.

### Duplicate Dictionary key(s)

Attempting to define a literal `DictionaryDictionaryDictionaryDictionaryDictionary` with one or more duplicated keys in the definition.

### Library or class function ... cannot be used without brackets

### a comment may not start with [ unless it is a recognised compiler directive

Compiler directives are a planned future capability. They will look like comments, but begin with an open square bracket. To avoid the possibility of ambiguity, you may not start your own comments with an open square bracket.

### Condition of 'if' expression does not evaluate to a Boolean.

### Cannot have any clause after unconditional 'else'.

### ... is a keyword, and may not be used as an identifier.

An Elan keyword cannot be used to as the name for a value, property, or method. Try shortening the name, lengthening it, or using a different name

For reference, the complete list of keywords is:
#, abstract, and, as, assert, be, call, catch, class, constant, constructor, copy, div, each, else, empty, end, enum, exception, for, from, function, global, if, image, import, in, inherits, interface, is, isnt, lambda, let, library, main, mod, new, not, of, or, out, print, private, procedure, property, record, ref, repeat, return, returns, set, step, test, then, this, throw, to, try, variable, while, with

### ... is a reserved word, and may not be used as an identifier.

In addition to Elan keywords there are other 'reserved words' that cannot be used to define the name for a value, property, or method. If you encounter this error you may eliminate the error simply by adding more valid characters to the name, but not by merely changing the case of part of the name.

Why are there any reserved words that are not Elan keywords? There are three kinds of reserved word:

- Potential keywords that might be added to Elan in future releases.
- Keywords in all the supported languages.
- Lowercase versions of Elan Type names, such as `IntintintIntegerint`, `FloatfloatdoubleDoubledouble`, `StringstrstringStringString`, `BooleanboolboolBooleanbool`, `ListlistListListList`, `DictionaryDictionaryDictionaryDictionaryDictionary`. It is not considered good practice to use Type names for identifiers: instead you should give each identifier a name that indicates what it does (for a method), or represents (for a named value).
- Words that are keywords in JavaScript (but not in Elan). Elan compiles to JavaScript and use of these words as identifiers could cause errors. (If you are asking, 'Why doesn't the Elan compiler just obfuscate these?' the answer is that we evaluated that option but concluded that it added a lot of complexity, especially in regard to debugging and interaction with the Elan editor, just to eliminate the minor inconvenience of having to extend the word so as to make your identifier distinct.)

For reference, the complete list of reserved words is:
action, arguments, array, async, await, boolean, break, by, byte, case, char, const, continue, curry, debugger, default, delete, dict, dictionary, do, double, error, eval, export, extends, final, finally, float, goto, ignore, implements, instanceof, int, into, list, long, match, myclass, namespace, native, null, on, optional, otherwise, package, partial, pattern, protected, public, short, static, string, super, switch, system, synchronized, throws, todo, transient, tuple, typeof, void, volatile, var, when, xor, yield

### Index cannot be negative.

An index into a list cannot have a negative value. If a negative is given in literal form e.g. a[−3] then this will generate a compile error. If you use a named value for an index and it is negative, then this will cause a runtime error.

### Cannot do equality operations on Procedures or Functions.

It is not possible to apply comparison operations to functions or procedures as themselves. It is, however, possible to compare the results of two function evaluations. You may see this message because you intended to evaluate a function but forgot to add the brackets after the name.

### ... cannot have key of type ...

The Type of the key for any dictionary Dictionary  must be an immutable Type, and not itself an indexable Type.

### Wrong number of deconstructed variables.

### referencing a property requires a prefix.

If you are referring to a property of a class from code defined within the class then the property name must be preceded by property.

### 'out' parameters are only supported on procedures.

You cannot defined an out parameter in a function (because that would imply the possibility of creating a side effect).

### There can only be one main in a program.

### Unsupported operation.

You cannot chain two 'unary' operators (those that apply to a single value), such as − or not successively within an expression.

### Parameter ... may not have the same name as the method in which it is defined.

A function or procedure named e.g. 'foo' may not define a parameter with that same name.

## Field help

### 'arguments' field in a call instruction

An argument list passed into a function or procedure call, must consist of one or more arguments separated by commas. Each argument may in general be any of:

- A literal value
- A named value
- An expression

In certain very specific contexts, however, some options are disallowed by the compiler.

### 'computed value' field in an assert instruction

The 'actual' field should be kept as simple as possible, preferably just a named value or a function evaluation. Generally, if you want to use a more complex expression, it is better to evaluate it in a preceding variable definition instruction and then use the named value in the 'actual' field of the assert equal instruction. Some more complex expressions are permissible, but these two restrictions apply:

- Any expression involving a binary operator such as +, isnt, etc., must have brackets around it.
- You may not use the is operator within the 'actual' field, because the parser will confuse this with the is keyword that is part of the assert equal instruction.

### 'variable name' field in a set instruction

The first field in a change variable instruction most commonly takes the name of an existing variable.

### 'comment' field

### literal value or data structure in a constant

The value of a constant must be a literal value of a Type that is not mutable. This can be a simple value (e.g. a number or string), or an immutable List or Dictionary.

### 'values' field in an enum definition

enum values must each be a valid identifier, separated by commas.

### 'message' field in a throw instruction

An exception message must be either a literal string or a named value holding a string.

### expression field - used within multiple instructions

This field expects an expression. For the various forms of expression see Expressions .

### identifier field - used within multiple instructions

### 'if' field in an else clause

### 'inherits className' field in a class

An inheritance clause, if used, must consist of the keyword inherits followed by a space and then one or more Type names separated by commas.

### 'name' field in a function or procedure definition

A method name must follow the rules for an identifier .

### 'parameter definitions' in a function or procedure definition

Each parameter definition takes the form:

name as Type

The name must follow the rules for an identifier .

The Type must follow the rules for a Type .

If more than one parameter is defined, the definitions must be separated by commas.

### 'procedureName' in a call statement

Valid forms for a procedure call are

- call procedure procedureName()
- call procedure instanceName.procedureMethodName()
- call procedure property.propertyName.procedureMethodName()
- call procedure library.procedureName()

The last one is used only if there is a need to disambiguate between a library procedure and a user-defined (global) procedure with the same name.

### 'Type' field in a function or property definition

For certain Types the name may be followed by an of clause, for example:

`ListlistListListList`<of `IntintintIntegerint`>
`DictionaryDictionaryDictionaryDictionaryDictionary`<of `StringstrstringStringString`, `IntintintIntegerint`>

### 'Name' field in a class or enum definition

Type names always begin with a capital letter, optionally followed by letters of either case, numeric digits, or underscore symbols. Nothing else.

### 'name' field in a let or variable instruction

The definition for a variable instruction is most commonly a simple name. Less commonly, it may take the form of a deconstruction of a `ListlistListListList`  or Tuple .

## Advisory

### Code change suggested. Method was deprecated in v7.1.

# Runtime errors

## Messages

### Tests timed out and were aborted

An error or infinite loop found in a test. Refer to ghosting tests .

### Overly complex expressions

Overly complex expressions, for example involving a sequence of open brackets, can result in very slow parsing. We strongly recommend that you you simplify the contents of this field, for example by breaking out parts of it into separate variable definition instructions; otherwise it might become impossible to add more text.

### ReferenceError: Cannot access '[name]' before initialisation

Elan Language Reference go to the top 