Procedural programming Reference

## Table of contents

### Main topics | Detailed topics

# Getting started

## Select the procedural programming paradigm

To undertake procedural programming (PP) in Elan, ensure that Elan is set to the procedural paradigm from the menu at the top of the IDE. This will ensure that:

- The list of demo programs will now show only programs that use PP.
- The options shown on the new code menus in the editor are all appropriate to PP. These are listed below under:
  - Global Instructions  and
  - Statement Instructions 

# Why coding with Elan is different

To start programming with Elan, first familiarise yourself with using the Elan IDE, especially for entering and editing code. Do this by watching the videos here . You will learn that Elan supports programming in Python, VB, C#, and Java (as well as the Reference Language Elan), and offers the option of immediate translation between these languages. If you have previously programmed in any of the languages you will find that Elan enforces best practice by means of the following constraints on how code is written. There are three forms of constraint, which are described in more detail in these sections:

1. Best practices in coding that Elan encourages
2. Use of a common library across all the supported languages 
3. Some, generally smaller, constraints needed for portability between the supported languages 

## Best practices in coding that Elan encourages

Elan supports, and in many cases enforces good programming practices, which are automatically applied across all the supported languages, even where a language ( when used outside Elan) would allow you to do otherwise. In the context of procedural programming (the procedural paradigm having been selected in the IDE), there are seven such best practices, some widely recognised, others less so.

Some programmers will argue that there are specific circumstances where breaking the rules should be acceptable. The problem with this is that most of the places where even professional programmers break the rules don't fit those circumstances: they are broken because the programmer just finds it more convenient. It is far better to learn to program without breaking these rules than that to adopt bad habits from the beginning. This will result in you writing better code and encountering fewer unexpected problems.

The six best practices enforced by Elan for procedural programming are:

1. No global variables 
2. Static typing 
3. No null references 
4. No breaking out of loops before they have completed 
5. Return from a function or procedure only after the final instruction 
6. All functions must be pure 

together with this seventh best practice that is supported and encouraged by Elan:

7. Every function should be unit tested 

### No global variables

It is widely recognised that global variables are a bad idea: they encourage poor program structure and lead to unexpected behaviour. Although most programming languages permit them, the Elan editor solves this by offering the variable definition  instruction only within the main routine, functions, and procedures. At global level the only permitted definition of a named value is a constant and that, too, is constrained to be of a type that cannot be mutated by any instruction in the program.

In Java, all code must be within a class. Elan provides a boilerplate class named Global to adhere to this rule, and all code must be within this. Everything added immediately within this class is deemed, in Elan terms, to be global, so you will not be able to add a variable, even in the form of a class property there.

### Static typing

Static typing means that the type of every variable, parameter, or value returned by a function, is known at compile time, and that type never changes, even though the value may change. VB, C#, and Java, are statically typed. but Python is inherently dynamically typed. Python 3.5 offers the option to add 'type hints' that assist working in a statically typed manner.

While some programmers like the idea of dynamic typing, there is almost no need for it in most forms of programming, and it is well established that dynamic typing does not work well when building large, complex systems. Moreover, in a purely educational context, using static typing gives a stronger understanding that, in all modern languages (with static or dynamic types) all data items always have an associated type, and static typing helps you to understand the nature of those types.

When entering and editing Python, Elan therefore enforces the use of type hints.

Elan does not require the type to be specified explicitly for any variable (or constant) because its type is inferred from the initial value given to it.

### No null references

All programmers have encountered the notorious 'Null Reference ...` (or 'Null Pointer ...`) error message, and the cause can sometimes be very hard to track down. Tony Hoare, Turing Medal recipient and one of Britain's greatest computer scientists, magnanimously described his invention of 'null' as a Billion Dollar Mistake.

All the supported programming languages inherently permit null reference errors, though when you are coding in Elan it is impossible for one to arise because:

- Every variable definition must specify an initial value
- It may never be assigned to null
- (Additional, related rules are enforced in object-oriented programming)

### No breaking out of loops before they have completed

Python, C#, and Java all have a break instruction (the VB equivalent is exit) which allows you to break out of a loop before its completion. Elan does not permit any of those instructions to be used for the following reasons.

The break instruction was invented when the only possible kind of loop that a programming language offered executed a specified number of times; there were no 'conditional loops'. With the advent of structured programming came proper conditional loops, of which the most common form is the while loop. With properly structured programming, it is never necessary to break out from a loop before its natural termination.

### Return from a function or procedure only after the final instruction

This principle is somewhat analogous to the previous one, in that programmers find it convenient to include multiple `returnreturnreturnreturnreturn` instructions within a procedure or a function. All the supported languages permit this. Elan, however, deliberately prevents this practice. An Elan function always has one return instruction as its last instruction (which specifies the value to be returned), and there is no option to add another one earlier. An Elan procedure cannot have a return instruction: the procedure exits after its last instruction.

Some programmers may argue that the constraint of no early returns in a function means you have to write an extra line of code at the start to define a variable to hold the result. This is true but it's a small price to pay and makes your code more readable

In summary, here are four reasons to avoid early returns:

- You cannot jump into the middle of a procedure or function, nor should you be able to jump out of it in the middle,
- They lead to poorly structured code,
- They make it harder to debug code because you may need to find, and put separate breakpoints on, every return statement,
- When you change the requirements of the function – for example so that a returned string is always upper case – you would need to enforce this in several places, running the risk of overlooking some. (Some languages offer a 'finally' clause to make that easier, but this is just a kludge to paper over the cracks of poor structure).

### All functions must be pure

Many textbooks draw no distinction between procedures and functions, except that the latter return a value to the code that references it. Used properly, the two are distinct in other, very important, respects.

A procedure:

- can be thought of as a way of adding you own custom instruction to the language,
- can make a change to the state of the system: which might be by printing a result on the screen, saving data to a file, or mutating a data structure passed into it, such as sorting a list 'in place' (see the Ripple Sort demo),
- may depend on the system in others ways, for example requesting a response from the user, or reading the system clock,
- must be called directly, never as part of an expression.

By contrast, a proper function:

- can be thought of as a way of adding a custom operator to the language – a way to derive a new value from one or more arguments,
- does not make any change to the state of the system. The only observable effect of referencing a function is the returned value, which is held, temporarily, on the system stack, to be consumed by something else. Another way to say this is that a function creates no side effects,
- may not depend on the system: the value returned must depend solely, and deterministically, on the values provided as parameters,
- should always be called where an expression is required, never in isolation (though the function call may constitute the complete expression). (Referencing a function in isolation – as you would for a procedure – is known as a 'hanging function call' because the returned value is not captured and used).

Although some programming languages make a syntactic distinction between a procedure and a function (some don't), the only ones that enforce the distinctions made above are the 'pure' functional programming languages, such as Haskell, OCAML, and F#.

Elan ensures that all functions are proper functions, but places no restrictions on what you can do in a procedure (except return a value). In the long term, if you wish to progress further with programming, laying this foundation will make it far easier for you to transition to functional programming than otherwise. But making this distinction from the outset offers more immediate benefits:

- Fewer bugs – specifically those arising from the unforeseen clashes between the side effects of procedures.
- Easier to reason about the correctness of the program, because functions behave more like mathematical functions. Specifically, if function foo is correct, and function bar is correct, then combining them in any way is also correct code. That cannot be inferred from combining two procedures.
- Functions can be more easily tested, which leads us on to our final best practice, as follows.

### Every function should be unit tested

Historically, most testing of programs was done by humans, manually running through a large number of 'test scripts' (or 'cases') to check that the delivered system worked correctly, then again after every single change or extension to the system, to ensure that existing functionality had not been broken accidentally.

In recent years, the emphasis has shifted to automated testing. Although writing the test scripts or cases still takes time, once written all the tests can be run repeatedly at the touch of a button, and even triggered automatically by any change to the code.

There are many forms of automated testing, but 'unit testing' is the most popular. All modern languages offer a 'unit testing framework', but they vary considerably in how easy they are to write and use.

Unit tests are intended for testing only proper functions though many languages do not enforce that. Running unit tests on procedures or on improper functions (that create side effects) can be dangerous – running the tests might result in data being written to a database, or a network message being sent repeatedly. There are software frameworks for automated testing of procedures and even whole applications (known as 'end to end testing'), but these frameworks are much harder to use.

Many professional software development teams enforce the writing of unit tests for every function, but this is typically something that most programmers don't discover unless they turn professional. But it is a practice that even complete beginners can benefit from:

- it gives you confidence that code is correct, especially code that you haven't looked at recently,
- it gives you an immediate sense of reward when all the tests pass – by going green,
- it gives you confidence to improve existing code (also known as 'refactoring') without the fear of unknowingly breaking it in subtle ways.

Elan provides unit testing for all the supported languages, and it is even simpler to use (both for writing the tests and running them) than most other tools. Although it does not enforce the rule that every function written should have automated unit tests, it does make it so easy that it hopefully encourages learners to use the practice.

## Use of a common library across all the supported languages

All programming languages have their own standard libraries for:

- mathematical and scientific functions,
- manipulating strings, lists, and other data structures,
- textual input/output,
- graphics.

and more. There are many similarities between the libraries of different languages, but also significant differences. Elan defines its own library which offers identical functions in each of the supported languages. The Elan library has been designed to find as much common ground as possible but, inevitably, it is not identical to the standard library for any of the supported languages.

One consequence of this is that even though the Python, C#, VB, or Java code generated within Elan is always syntactically valid for the language, you won't typically be able to run exported code in another environment without editing the library calls. (We hope to provide automated, or semi-automated, tools for this in the future).

## Other constraints

Elan enforces a few other constraints that aren't driven by best practices, or by the common library, but because of small arbitrary differences between the target languages. Fortunately these are quite small both in number and impact. There is no need to learn them explicitly, because in all cases where you might encounter one, you will get a clear error message that gives you the solution. But here is a list of the most important ones:

- Elan is case-sensitive for identifiers, but you deliberately cannot define two identifiers in the same scope that differ only by case.
- All languages disallow the use of certain reserved words as identifiers. Elan deliberately disallows the reserved words from all the supported languages, so translations are guaranteed to run.
- Literal strings must be bounded by double quotes, not by single quotes
- Some languages distinguish between a 'for loop' and a 'for each loop'. Elan, like Python, uses the same syntax for both. When you use a for loop in Elan, the syntax in VB, C#, and Java will be that of a 'for each' loop.
- Raising a number to a power must be done with the pow function: the 'power operator' symbol in the supported languages will not be recognised.
- Individual values are extracted from a tuple using the syntax `myTuple.item_0myTuple.item_0myTuple.item_0myTuple.item_0myTuple.item_0`, `myTuple.item_1myTuple.item_1myTuple.item_1myTuple.item_1myTuple.item_1`, etc. Special 'tuple deconstruction' syntax is not recognised for any of the languages.
- Equality testing of value types uses the equality operator for each language e.g. `a is ba == ba == ba = ba == b`, but if the types are reference types (e.g. lists or strings) you must use the syntax `a.equals(b)a.equals(b)a.equals(b)a.equals(b)a.equals(b)`
- Division of two floating point numbers (or one floating point and one integer) may use the division operator `a/ba/ba/ba/ba/b` and the result will always be floating point. But if both values are of integer type then you must use either `divAsInt(a, b)divAsInt(a, b)divAsInt(a, b)divAsInt(a, b)divAsInt(a, b)` or `divAsFloat(a, b)divAsFloat(a, b)divAsFloat(a, b)divAsFloat(a, b)divAsFloat(a, b)` to make clear which result you are looking for (divAsInt will round down the result if necessary).
- A 2-dimensional arrays is implemented as a list of lists.
- Negative index values and index ranges are not supported.
- Passing by reference is done by wrapping a parameter of type `IntintintIntegerint`, say, in `AsRef<of Int>AsRef[int]AsRef<int>AsRef(Of Integer)AsRef<int>`.

# Global instructions

In Python, VB, C#, and the Reference Language, global instructions are placed directly in your code file, not within other code, and are therefore not indented.

Java note

All Java code must be within a class so, when writing Java with Elan, the editor generates a non-editable class named Global, and all global instructions are created directly within that (and automatically indented).

## Main routine

### Examples of a main routine

From the Burrow demo. For very simple applications like this, the main routine is the whole program:

+main 70 variable blocks name? set to createBlockGraphics(white)value or expression?71 variable x name? set to 20 value or expression?72 variable y name? set to 15 value or expression?73 +while true condition? 74 assign blocks[x][y]variableName? to red value or expression?75 call displayBlocks procedureName?(blocks arguments?)76 assign blocks[x][y]variableName? to black value or expression?77 variable direction name? set to randint(0, 3)value or expression?78 +if direction is 0 condition? then 79 assign x variableName? to min([x + 1, 39])value or expression?80 elif direction is 1 condition? then 81 assign x variableName? to max([x - 1, 0])value or expression?82 elif direction is 2 condition? then 83 assign y variableName? to min([y + 1, 29])value or expression?84 elif direction is 3 condition? then 85 assign y variableName? to max([y - 1, 0])value or expression?86 end if end while end main
+def main() -> None: 87 blocks name? = createBlockGraphics(white)value or expression? # variable definition 88 x name? = 20 value or expression? # variable definition 89 y name? = 15 value or expression? # variable definition 90 +while True condition?: 91 blocks[x][y]variableName? = red value or expression? # assignment 92 displayBlocks procedureName?(blocks arguments?) # procedure call 93 blocks[x][y]variableName? = black value or expression? # assignment 94 direction name? = randint(0, 3)value or expression? # variable definition 95 +if direction == 0 condition?: 96 x variableName? = min([x + 1, 39])value or expression? # assignment 97 elif direction == 1 condition?: # else if 98 x variableName? = max([x - 1, 0])value or expression? # assignment 99 elif direction == 2 condition?: # else if 100 y variableName? = min([y + 1, 29])value or expression? # assignment 101 elif direction == 3 condition?: # else if 102 y variableName? = max([y - 1, 0])value or expression? # assignment 103 # end if # end while # end main
+static void main() { 104 var blocks name? = createBlockGraphics(white)value or expression?;105 var x name? = 20 value or expression?;106 var y name? = 15 value or expression?;107 +while (true condition?) { 108 blocks[x][y]variableName? = red value or expression?; // assignment 109 displayBlocks procedureName?(blocks arguments?); // procedure call 110 blocks[x][y]variableName? = black value or expression?; // assignment 111 var direction name? = randint(0, 3)value or expression?;112 +if (direction == 0 condition?) { 113 x variableName? = min(new [] {x + 1, 39})value or expression?; // assignment 114 } else if (direction == 1 condition?) {115 x variableName? = max(new [] {x - 1, 0})value or expression?; // assignment 116 } else if (direction == 2 condition?) {117 y variableName? = min(new [] {y + 1, 29})value or expression?; // assignment 118 } else if (direction == 3 condition?) {119 y variableName? = max(new [] {y - 1, 0})value or expression?; // assignment 120 } // end if } // end while } // end main
+Sub main() 121 Dim blocks name? = createBlockGraphics(white)value or expression? ' variable definition 122 Dim x name? = 20 value or expression? ' variable definition 123 Dim y name? = 15 value or expression? ' variable definition 124 +While True condition? 125 blocks(x)(y)variableName? = red value or expression? ' assignment 126 displayBlocks procedureName?(blocks arguments?) ' procedure call 127 blocks(x)(y)variableName? = black value or expression? ' assignment 128 Dim direction name? = randint(0, 3)value or expression? ' variable definition 129 +If direction = 0 condition? Then 130 x variableName? = min({x + 1, 39})value or expression? ' assignment 131 ElseIf direction = 1 condition? Then 132 x variableName? = max({x - 1, 0})value or expression? ' assignment 133 ElseIf direction = 2 condition? Then 134 y variableName? = min({y + 1, 29})value or expression? ' assignment 135 ElseIf direction = 3 condition? Then 136 y variableName? = max({y - 1, 0})value or expression? ' assignment 137 End If End While End Sub
+static void main() { 138 var blocks name? = createBlockGraphics(white)value or expression?;139 var x name? = 20 value or expression?;140 var y name? = 15 value or expression?;141 +while (true condition?) { 142 blocks[x][y]variableName? = red value or expression?; // assignment 143 displayBlocks procedureName?(blocks arguments?); // procedure call 144 blocks[x][y]variableName? = black value or expression?; // assignment 145 var direction name? = randint(0, 3)value or expression?;146 +if (direction == 0 condition?) { 147 x variableName? = min(list(x + 1, 39))value or expression?; // assignment 148 } else if (direction == 1 condition?) {149 x variableName? = max(list(x - 1, 0))value or expression?; // assignment 150 } else if (direction == 2 condition?) {151 y variableName? = min(list(y + 1, 29))value or expression?; // assignment 152 } else if (direction == 3 condition?) {153 y variableName? = max(list(y - 1, 0))value or expression?; // assignment 154 } // end if } // end while } // end main

From the Ripple Sort demo. The main routine defines the list to be sorted, delegates most of the work to the inPlaceRippleSort procedure (not shown here), then prints the sorted list:

+main 155 variable li name? set to [3, 6, 1, 0, 99, 4, 67]value or expression?156 call inPlaceRippleSort procedureName?(li arguments?)157 print(li arguments?)158 end main
+def main() -> None: 159 li name? = [3, 6, 1, 0, 99, 4, 67]value or expression? # variable definition 160 inPlaceRippleSort procedureName?(li arguments?) # procedure call 161 print(li arguments?)162 # end main
+static void main() { 163 var li name? = new [] {3, 6, 1, 0, 99, 4, 67}value or expression?;164 inPlaceRippleSort procedureName?(li arguments?); // procedure call 165 Console.WriteLine(li arguments?); // print statement 166 } // end main
+Sub main() 167 Dim li name? = {3, 6, 1, 0, 99, 4, 67}value or expression? ' variable definition 168 inPlaceRippleSort procedureName?(li arguments?) ' procedure call 169 Console.WriteLine(li arguments?) ' print statement 170 End Sub
+static void main() { 171 var li name? = list(3, 6, 1, 0, 99, 4, 67)value or expression?;172 inPlaceRippleSort procedureName?(li arguments?); // procedure call 173 System.out.println(li arguments?); // print statement 174 } // end main

From the Life – procedural demo. The whole program is 157 instructions (including tests), but the main routine contains just 9. It is good practice to keep the main routine small.

+main 175 variable grid name? set to createBlockGraphics(white)value or expression?176 call fillRandom procedureName?(grid arguments?)177 +while true condition? 178 call displayBlocks procedureName?(grid arguments?)179 variable gridRef name? set to new AsRef<of List<of List<of Int>>>(grid)value or expression?180 call nextGeneration procedureName?(gridRef arguments?)181 assign grid variableName? to gridRef.value()value or expression?182 call sleep_ms procedureName?(50 arguments?)183 end while end main
+def main() -> None: 184 grid name? = createBlockGraphics(white)value or expression? # variable definition 185 fillRandom procedureName?(grid arguments?) # procedure call 186 +while True condition?: 187 displayBlocks procedureName?(grid arguments?) # procedure call 188 gridRef name? = AsRef[list[list[int]]](grid)value or expression? # variable definition 189 nextGeneration procedureName?(gridRef arguments?) # procedure call 190 grid variableName? = gridRef.value()value or expression? # assignment 191 sleep_ms procedureName?(50 arguments?) # procedure call 192 # end while # end main
+static void main() { 193 var grid name? = createBlockGraphics(white)value or expression?;194 fillRandom procedureName?(grid arguments?); // procedure call 195 +while (true condition?) { 196 displayBlocks procedureName?(grid arguments?); // procedure call 197 var gridRef name? = new AsRef<List<List<int>>>(grid)value or expression?;198 nextGeneration procedureName?(gridRef arguments?); // procedure call 199 grid variableName? = gridRef.value()value or expression?; // assignment 200 sleep_ms procedureName?(50 arguments?); // procedure call 201 } // end while } // end main
+Sub main() 202 Dim grid name? = createBlockGraphics(white)value or expression? ' variable definition 203 fillRandom procedureName?(grid arguments?) ' procedure call 204 +While True condition? 205 displayBlocks procedureName?(grid arguments?) ' procedure call 206 Dim gridRef name? = New AsRef(Of List(Of List(Of Integer)))(grid)value or expression? ' variable definition 207 nextGeneration procedureName?(gridRef arguments?) ' procedure call 208 grid variableName? = gridRef.value()value or expression? ' assignment 209 sleep_ms procedureName?(50 arguments?) ' procedure call 210 End While End Sub
+static void main() { 211 var grid name? = createBlockGraphics(white)value or expression?;212 fillRandom procedureName?(grid arguments?); // procedure call 213 +while (true condition?) { 214 displayBlocks procedureName?(grid arguments?); // procedure call 215 var gridRef name? = new AsRef<List<List<int>>>(grid)value or expression?;216 nextGeneration procedureName?(gridRef arguments?); // procedure call 217 grid variableName? = gridRef.value()value or expression?; // assignment 218 sleep_ms procedureName?(50 arguments?); // procedure call 219 } // end while } // end main

### What you need to know about a main routine

- The first instruction added within the main routine, is always the first instruction to be executed when the program is run.
- Without a main routine, there is nothing to run. However you may write and test functions without a main.
- The main routine does not have to be at the top of the file, but this is a good convention to follow.
- You may not add another main routine within a program, unless you first ghost the existing one.
- The main routine may form the entire program (as in the Burrow example above). More commonly it will delegate to procedures and functions that you define.

## Procedure

### Examples of a procedure

From the Bubbles demo, this procedure changes the vertical position, and the size, of each bubble in the provided list:

+procedure moveGrowBurst name?(bubbles as List<of CircleVG>parameter definitions?) 220 +for b item? in bubbles source? 221 +if random() < 0.05 condition? then 222 # 5% chance bubble 'bursts' and starts again tiny at bottom comment? call b.setRadius procedureName?(0 arguments?)223 call b.setCentreY procedureName?(75 arguments?)224 else 225 # bubble rises and grows slightly comment? call b.setCentreY procedureName?(b.centreY - 1 arguments?)226 call b.setRadius procedureName?(b.radius + 0.2 arguments?)227 end if end for call displayVectorGraphics procedureName?(bubbles arguments?)228 call sleep_ms procedureName?(5 arguments?)229 end procedure
+def moveGrowBurst name?(bubbles: list[CircleVG]parameter definitions?) -> None: # procedure 230 +for b item? in bubbles source?: 231 +if random() < 0.05 condition?: 232 # 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?) # procedure call 233 b.setCentreY procedureName?(75 arguments?) # procedure call 234 else:235 # bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?) # procedure call 236 b.setRadius procedureName?(b.radius + 0.2 arguments?) # procedure call 237 # end if # end for displayVectorGraphics procedureName?(bubbles arguments?) # procedure call 238 sleep_ms procedureName?(5 arguments?) # procedure call 239 # end procedure
+static void moveGrowBurst name?(List<CircleVG> bubbles parameter definitions?) { // procedure 240 +foreach (var b item? in bubbles source?) { 241 +if (random() < 0.05 condition?) { 242 // 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?); // procedure call 243 b.setCentreY procedureName?(75 arguments?); // procedure call 244 } else {245 // bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?); // procedure call 246 b.setRadius procedureName?(b.radius + 0.2 arguments?); // procedure call 247 } // end if } // end foreach displayVectorGraphics procedureName?(bubbles arguments?); // procedure call 248 sleep_ms procedureName?(5 arguments?); // procedure call 249 } // end procedure
+Sub moveGrowBurst name?(bubbles As List(Of CircleVG)parameter definitions?) ' procedure 250 +For Each b item? In bubbles source? 251 +If random() < 0.05 condition? Then 252 ' 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?) ' procedure call 253 b.setCentreY procedureName?(75 arguments?) ' procedure call 254 Else 255 ' bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?) ' procedure call 256 b.setRadius procedureName?(b.radius + 0.2 arguments?) ' procedure call 257 End If Next b displayVectorGraphics procedureName?(bubbles arguments?) ' procedure call 258 sleep_ms procedureName?(5 arguments?) ' procedure call 259 End Sub
+static void moveGrowBurst name?(List<CircleVG> bubbles parameter definitions?) { // procedure 260 +foreach (var b item? in bubbles source?) { 261 +if (random() < 0.05 condition?) { 262 // 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?); // procedure call 263 b.setCentreY procedureName?(75 arguments?); // procedure call 264 } else {265 // bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?); // procedure call 266 b.setRadius procedureName?(b.radius + 0.2 arguments?); // procedure call 267 } // end if } // end foreach displayVectorGraphics procedureName?(bubbles arguments?); // procedure call 268 sleep_ms procedureName?(5 arguments?); // procedure call 269 } // end procedure

It is called within the main routine by this instruction:

`call moveGrowBurstprocedureName?(bubblesarguments?)0moveGrowBurstprocedureName?(bubblesarguments?) # procedure call1moveGrowBurstprocedureName?(bubblesarguments?); // procedure call2moveGrowBurstprocedureName?(bubblesarguments?) ' procedure call3moveGrowBurstprocedureName?(bubblesarguments?); // procedure call4`

From the Turtle Dragon demo, this procedure defines two parameters of different types. The body of this procedure consists of a straight sequence of procedure calls, but all the procedures are defined on the turtle (the parameter named `ttttt`) using 'dot syntax':

+procedure setupTurtle name?(t as Turtle, order as Int parameter definitions?) 270 call t.turnToHeading procedureName?(180 + order*45 arguments?)271 call t.placeAt procedureName?(-40, 20 arguments?)272 call t.penColour procedureName?(red arguments?)273 call t.penWidth procedureName?(10.0/order arguments?)274 call t.penDown procedureName?(arguments?)275 call t.show procedureName?(arguments?)276 end procedure
+def setupTurtle name?(t: Turtle, order: int parameter definitions?) -> None: # procedure 277 t.turnToHeading procedureName?(180 + order*45 arguments?) # procedure call 278 t.placeAt procedureName?(-40, 20 arguments?) # procedure call 279 t.penColour procedureName?(red arguments?) # procedure call 280 t.penWidth procedureName?(10.0/order arguments?) # procedure call 281 t.penDown procedureName?(arguments?) # procedure call 282 t.show procedureName?(arguments?) # procedure call 283 # end procedure
+static void setupTurtle name?(Turtle t, int order parameter definitions?) { // procedure 284 t.turnToHeading procedureName?(180 + order*45 arguments?); // procedure call 285 t.placeAt procedureName?(-40, 20 arguments?); // procedure call 286 t.penColour procedureName?(red arguments?); // procedure call 287 t.penWidth procedureName?(10.0/order arguments?); // procedure call 288 t.penDown procedureName?(arguments?); // procedure call 289 t.show procedureName?(arguments?); // procedure call 290 } // end procedure
+Sub setupTurtle name?(t As Turtle, order As Integer parameter definitions?) ' procedure 291 t.turnToHeading procedureName?(180 + order*45 arguments?) ' procedure call 292 t.placeAt procedureName?(-40, 20 arguments?) ' procedure call 293 t.penColour procedureName?(red arguments?) ' procedure call 294 t.penWidth procedureName?(10.0/order arguments?) ' procedure call 295 t.penDown procedureName?(arguments?) ' procedure call 296 t.show procedureName?(arguments?) ' procedure call 297 End Sub
+static void setupTurtle name?(Turtle t, int order parameter definitions?) { // procedure 298 t.turnToHeading procedureName?(180 + order*45 arguments?); // procedure call 299 t.placeAt procedureName?(-40, 20 arguments?); // procedure call 300 t.penColour procedureName?(red arguments?); // procedure call 301 t.penWidth procedureName?(10.0/order arguments?); // procedure call 302 t.penDown procedureName?(arguments?); // procedure call 303 t.show procedureName?(arguments?); // procedure call 304 } // end procedure

From the Life – procedural demo, this code sets each of the cells in the 40×30 `gridgridgridgridgrid`

+procedure fillRandom name?(grid as List<of List<of Int>>parameter definitions?) 305 +for col item? in range(0, 40)source? 306 +for row item? in range(0, 30)source? 307 assign grid[col][row]variableName? to blackOrWhite(random())value or expression?308 end for end for end procedure
+def fillRandom name?(grid: list[list[int]]parameter definitions?) -> None: # procedure 309 +for col item? in range(0, 40)source?: 310 +for row item? in range(0, 30)source?: 311 grid[col][row]variableName? = blackOrWhite(random())value or expression? # assignment 312 # end for # end for # end procedure
+static void fillRandom name?(List<List<int>> grid parameter definitions?) { // procedure 313 +foreach (var col item? in range(0, 40)source?) { 314 +foreach (var row item? in range(0, 30)source?) { 315 grid[col][row]variableName? = blackOrWhite(random())value or expression?; // assignment 316 } // end foreach } // end foreach } // end procedure
+Sub fillRandom name?(grid As List(Of List(Of Integer))parameter definitions?) ' procedure 317 +For Each col item? In range(0, 40)source? 318 +For Each row item? In range(0, 30)source? 319 grid(col)(row)variableName? = blackOrWhite(random())value or expression? ' assignment 320 Next row Next col End Sub
+static void fillRandom name?(List<List<int>> grid parameter definitions?) { // procedure 321 +foreach (var col item? in range(0, 40)source?) { 322 +foreach (var row item? in range(0, 30)source?) { 323 grid[col][row]variableName? = blackOrWhite(random())value or expression?; // assignment 324 } // end foreach } // end foreach } // end procedure

### What you need to know about a procedure

- A procedure (also known as a 'subroutine') defines a part of the program to which work is delegated, either by the main routine, or by another procedure.
- The Elan library provides some ready-made procedures such as print and pause.
- The procedure instruction allows you to define your own procedures.
- A procedure is defined with a unique name, starting lower case (e.g. moveGrowBurst).
- It may optionally define one or more parameters (one in moveGrowBurst, two in setupTurtle), comma-separated if more than one.
- Each parameter specifies a name, starting lower case (`bubblesbubblesbubblesbubblesbubbles` above) and a type (`List<of CircleVG>list[CircleVG]List<CircleVG>List(Of CircleVG)List<CircleVG>` above) using the syntax `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.`
- The procedure is called from elsewhere using a procedure call, which specifies the name of the procedure to be called and includes values or expressions (known as arguments) that match the types of the parameters.
- The procedure always finishes on the last instruction defined within it, at which point the program continues from where the call instruction is located.
- Changes made to parameter values (where possible) within the procedure (such as changing the radius and centre of each bubble in the list `bubblesbubblesbubblesbubblesbubbles`) will be visible to the calling code when the procedure exits.
- Functions may be called from within a procedure, but not vice versa.
- Instructions within a procedure – unlike within a function – may call other procedures, undertake input/output, and use system methods.

### More advanced techniques

#### Call by reference

To change the value in named value `argargargargarg` 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 of type `AsRefAsRefAsRefAsRefAsRef`. This then allows use of the dot methods set and value on it to change and then read its value, as in this example where `argRefargRefargRefargRefargRef` is a pointer to variable `argargargargarg` in the main routine, so that `argargargargarg` can be accessed elsewhere by reference:

+main 325 variable arg name? set to "abc"value or expression?326 variable argRef name? set to new AsRef<of String>(arg)value or expression?327 call changeArg procedureName?(argRef arguments?)328 print(argRef.value()arguments?)329 end main
+def main() -> None: 330 arg name? = "abc"value or expression? # variable definition 331 argRef name? = AsRef[str](arg)value or expression? # variable definition 332 changeArg procedureName?(argRef arguments?) # procedure call 333 print(argRef.value()arguments?)334 # end main
+static void main() { 335 var arg name? = "abc"value or expression?;336 var argRef name? = new AsRef<string>(arg)value or expression?;337 changeArg procedureName?(argRef arguments?); // procedure call 338 Console.WriteLine(argRef.value()arguments?); // print statement 339 } // end main
+Sub main() 340 Dim arg name? = "abc"value or expression? ' variable definition 341 Dim argRef name? = New AsRef(Of String)(arg)value or expression? ' variable definition 342 changeArg procedureName?(argRef arguments?) ' procedure call 343 Console.WriteLine(argRef.value()arguments?) ' print statement 344 End Sub
+static void main() { 345 var arg name? = "abc"value or expression?;346 var argRef name? = new AsRef<String>(arg)value or expression?;347 changeArg procedureName?(argRef arguments?); // procedure call 348 System.out.println(argRef.value()arguments?); // print statement 349 } // end main

### Recursive procedure calls

A procedure may call itself, directly or indirectly (calling another procedure that then calls back to the first one). In the following example is from the Turtle Snowflake demo, you can see that the drawSide procedure calls itself from four separate places within its body – in order to achieve the 'fractal' effect, where a basic shape repeats itself at different levels of scale. You can also observe two very important principles of recursion here:

- Calls back into itself are with a smaller version of the problem – in this case one third of the `lengthlengthlengthlengthlength` that the procedure was given.
- There is a terminating condition where the recursion 'bottoms out' – in this when the side length gets down to 1.

+procedure drawSide name?(length as Float, t as Turtle parameter definitions?) 350 +if (length > 1)condition? then 351 variable third name? set to length/3 value or expression?352 call drawSide procedureName?(third, t arguments?)353 call t.turn procedureName?(-60 arguments?)354 call drawSide procedureName?(third, t arguments?)355 call t.turn procedureName?(120 arguments?)356 call drawSide procedureName?(third, t arguments?)357 call t.turn procedureName?(-60 arguments?)358 call drawSide procedureName?(third, t arguments?)359 else 360 call t.move procedureName?(length arguments?)361 end if end procedure
+def drawSide name?(length: float, t: Turtle parameter definitions?) -> None: # procedure 362 +if (length > 1)condition?: 363 third name? = length/3 value or expression? # variable definition 364 drawSide procedureName?(third, t arguments?) # procedure call 365 t.turn procedureName?(-60 arguments?) # procedure call 366 drawSide procedureName?(third, t arguments?) # procedure call 367 t.turn procedureName?(120 arguments?) # procedure call 368 drawSide procedureName?(third, t arguments?) # procedure call 369 t.turn procedureName?(-60 arguments?) # procedure call 370 drawSide procedureName?(third, t arguments?) # procedure call 371 else:372 t.move procedureName?(length arguments?) # procedure call 373 # end if # end procedure
+static void drawSide name?(double length, Turtle t parameter definitions?) { // procedure 374 +if ((length > 1)condition?) { 375 var third name? = length/3 value or expression?;376 drawSide procedureName?(third, t arguments?); // procedure call 377 t.turn procedureName?(-60 arguments?); // procedure call 378 drawSide procedureName?(third, t arguments?); // procedure call 379 t.turn procedureName?(120 arguments?); // procedure call 380 drawSide procedureName?(third, t arguments?); // procedure call 381 t.turn procedureName?(-60 arguments?); // procedure call 382 drawSide procedureName?(third, t arguments?); // procedure call 383 } else {384 t.move procedureName?(length arguments?); // procedure call 385 } // end if } // end procedure
+Sub drawSide name?(length As Double, t As Turtle parameter definitions?) ' procedure 386 +If (length > 1)condition? Then 387 Dim third name? = length/3 value or expression? ' variable definition 388 drawSide procedureName?(third, t arguments?) ' procedure call 389 t.turn procedureName?(-60 arguments?) ' procedure call 390 drawSide procedureName?(third, t arguments?) ' procedure call 391 t.turn procedureName?(120 arguments?) ' procedure call 392 drawSide procedureName?(third, t arguments?) ' procedure call 393 t.turn procedureName?(-60 arguments?) ' procedure call 394 drawSide procedureName?(third, t arguments?) ' procedure call 395 Else 396 t.move procedureName?(length arguments?) ' procedure call 397 End If End Sub
+static void drawSide name?(double length, Turtle t parameter definitions?) { // procedure 398 +if ((length > 1)condition?) { 399 var third name? = length/3 value or expression?;400 drawSide procedureName?(third, t arguments?); // procedure call 401 t.turn procedureName?(-60 arguments?); // procedure call 402 drawSide procedureName?(third, t arguments?); // procedure call 403 t.turn procedureName?(120 arguments?); // procedure call 404 drawSide procedureName?(third, t arguments?); // procedure call 405 t.turn procedureName?(-60 arguments?); // procedure call 406 drawSide procedureName?(third, t arguments?); // procedure call 407 } else {408 t.move procedureName?(length arguments?); // procedure call 409 } // end if } // end procedure

## Function

### Examples of a function

From the Snake – procedural demo. Given the coordinates of the snake's head, determines whether or not the head has gone outside the bounds of the 40x30 grid:

+function hasHitEdge name?(headX as Int, headY as Int parameter definitions?) returns Boolean Type? 410 return (headX < 0) or (headY < 0) or (headX > 39) or (headY > 29)value or expression?411 end function
+def hasHitEdge name?(headX: int, headY: int parameter definitions?) -> bool Type?: # function 412 return (headX < 0) or (headY < 0) or (headX > 39) or (headY > 29)value or expression?413 # end function
+static bool Type? hasHitEdge name?(int headX, int headY parameter definitions?) { // function 414 return (headX < 0) || (headY < 0) || (headX > 39) || (headY > 29)value or expression?;415 } // end function
+Function hasHitEdge name?(headX As Integer, headY As Integer parameter definitions?) As Boolean Type? 416 Return (headX < 0) Or (headY < 0) Or (headX > 39) Or (headY > 29)value or expression?417 End Function
+static boolean Type? hasHitEdge name?(int headX, int headY parameter definitions?) { // function 418 return (headX < 0) || (headY < 0) || (headX > 39) || (headY > 29)value or expression?;419 } // end function

It is called within the main routine as part of this instruction:

assign gameOn variableName? to not hasHitEdge(head[0], head[1]) and not body.contains(head)value or expression?420
gameOn variableName? = not hasHitEdge(head[0], head[1]) and not body.contains(head)value or expression? # assignment 421
gameOn variableName? = !hasHitEdge(head[0], head[1]) && !body.contains(head)value or expression?; // assignment 422
gameOn variableName? = Not hasHitEdge(head(0), head(1)) And Not body.contains(head)value or expression? ' assignment 423
gameOn variableName? = !hasHitEdge(head[0], head[1]) && !body.contains(head)value or expression?; // assignment 424

From the Life – procedural demo a function that finds the cell immediately to the north of the cell provided. Both the single parameter and return value are 2-tuples, where both items are of type `IntintintIntegerint`:

+function north name?(cell as (Int, Int)parameter definitions?) returns (Int, Int)Type? 435 variable x name? set to cell.item_0 value or expression?436 variable y name? set to cell.item_1 value or expression?437 variable y2 name? set to y - 1 value or expression?438 +if y2 is -1 condition? then 439 assign y2 variableName? to 29 value or expression?440 end if return (x, y2)value or expression?441 end function
+def north name?(cell: tuple[int, int]parameter definitions?) -> tuple[int, int]Type?: # function 442 x name? = cell.item_0 value or expression? # variable definition 443 y name? = cell.item_1 value or expression? # variable definition 444 y2 name? = y - 1 value or expression? # variable definition 445 +if y2 == -1 condition?: 446 y2 variableName? = 29 value or expression? # assignment 447 # end if return (x, y2)value or expression?448 # end function
+static (int, int)Type? north name?((int, int) cell parameter definitions?) { // function 449 var x name? = cell.item_0 value or expression?;450 var y name? = cell.item_1 value or expression?;451 var y2 name? = y - 1 value or expression?;452 +if (y2 == -1 condition?) { 453 y2 variableName? = 29 value or expression?; // assignment 454 } // end if return (x, y2)value or expression?;455 } // end function
+Function north name?(cell As (Integer, Integer)parameter definitions?) As (Integer, Integer)Type? 456 Dim x name? = cell.item_0 value or expression? ' variable definition 457 Dim y name? = cell.item_1 value or expression? ' variable definition 458 Dim y2 name? = y - 1 value or expression? ' variable definition 459 +If y2 = -1 condition? Then 460 y2 variableName? = 29 value or expression? ' assignment 461 End If Return (x, y2)value or expression?462 End Function
+static (int, int)Type? north name?((int, int) cell parameter definitions?) { // function 463 var x name? = cell.item_0 value or expression?;464 var y name? = cell.item_1 value or expression?;465 var y2 name? = y - 1 value or expression?;466 +if (y2 == -1 condition?) { 467 y2 variableName? = 29 value or expression?; // assignment 468 } // end if return (x, y2)value or expression?;469 } // end function

A function to search a (pre-sorted) list of strings using the binary search algorithm:

+function binarySearch name?(li as List<of String>, item as String parameter definitions?) returns Boolean Type? 470 variable result name? set to false value or expression?471 +if li.length() > 0 condition? then 472 variable mid name? set to divAsInt(li.length(), 2)value or expression?473 variable value name? set to li[mid]value or expression?474 +if item.equals(value)condition? then 475 assign result variableName? to true value or expression?476 elif item.isBefore(value)condition? then 477 assign result variableName? to binarySearch(li.subList(0, mid), item)value or expression?478 else 479 assign result variableName? to binarySearch(li.subList(mid + 1, li.length()), item)value or expression?480 end if end if return result value or expression?481 end function
+def binarySearch name?(li: list[str], item: str parameter definitions?) -> bool Type?: # function 482 result name? = False value or expression? # variable definition 483 +if li.length() > 0 condition?: 484 mid name? = divAsInt(li.length(), 2)value or expression? # variable definition 485 value name? = li[mid]value or expression? # variable definition 486 +if item.equals(value)condition?: 487 result variableName? = True value or expression? # assignment 488 elif item.isBefore(value)condition?: # else if 489 result variableName? = binarySearch(li.subList(0, mid), item)value or expression? # assignment 490 else:491 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression? # assignment 492 # end if # end if return result value or expression?493 # end function
+static bool Type? binarySearch name?(List<string> li, string item parameter definitions?) { // function 494 var result name? = false value or expression?;495 +if (li.length() > 0 condition?) { 496 var mid name? = divAsInt(li.length(), 2)value or expression?;497 var value name? = li[mid]value or expression?;498 +if (item.equals(value)condition?) { 499 result variableName? = true value or expression?; // assignment 500 } else if (item.isBefore(value)condition?) {501 result variableName? = binarySearch(li.subList(0, mid), item)value or expression?; // assignment 502 } else {503 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression?; // assignment 504 } // end if } // end if return result value or expression?;505 } // end function
+Function binarySearch name?(li As List(Of String), item As String parameter definitions?) As Boolean Type? 506 Dim result name? = False value or expression? ' variable definition 507 +If li.length() > 0 condition? Then 508 Dim mid name? = divAsInt(li.length(), 2)value or expression? ' variable definition 509 Dim value name? = li(mid)value or expression? ' variable definition 510 +If item.equals(value)condition? Then 511 result variableName? = True value or expression? ' assignment 512 ElseIf item.isBefore(value)condition? Then 513 result variableName? = binarySearch(li.subList(0, mid), item)value or expression? ' assignment 514 Else 515 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression? ' assignment 516 End If End If Return result value or expression?517 End Function
+static boolean Type? binarySearch name?(List<String> li, String item parameter definitions?) { // function 518 var result name? = false value or expression?;519 +if (li.length() > 0 condition?) { 520 var mid name? = divAsInt(li.length(), 2)value or expression?;521 var value name? = li[mid]value or expression?;522 +if (item.equals(value)condition?) { 523 result variableName? = true value or expression?; // assignment 524 } else if (item.isBefore(value)condition?) {525 result variableName? = binarySearch(li.subList(0, mid), item)value or expression?; // assignment 526 } else {527 result variableName? = binarySearch(li.subList(mid + 1, li.length()), item)value or expression?; // assignment 528 } // end if } // end if return result value or expression?;529 } // end function

### What you need to know about a function

- A function defines a mechanism to transform input data (passed as parameters) into a single returned value that may be of any type including a data structure.
- Because it generates a value, a function reference is a kind of expression – it may define a complete expression, or be a part of a more complex expression (as above).
- The Elan library provides some ready-made functions such as sqrt.
- The function instruction allows you to define your own functions.
- A function is defined with a unique name (starting with a lower case letter, e.g. hasHitEdge).
- It will usually define one or more parameters (two in the example above), comma-separated if more than one.
- Each parameter specifies a name starting in lower case (`headXheadXheadXheadXheadX` above) and a type (`IntintintIntegerint` above) using the syntax `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.`
- A function's first (definition) line – its signature – must also specify the type of value it will return (`returnsreturnsreturnsreturnsreturns` `BooleanboolboolBooleanboolean` above).
- As with the parameters, the returned value may be a simple value such as an `IntintintIntegerint`, or it may be a data structure such as a `List<of Float>list[float]List<double>List(Of Double)List<double>`.
- A function always has a `returnreturnreturnreturnreturn` instruction as its last instruction, which specifies a value, or an expression to be evaluated. The value, or the result of evaluating the expression, must yield the same type as specified in the signature.
- Even though some languages would allow you to put the `returnreturnreturnreturnreturn` anywhere within the function, or even have more than one of them, Elan deliberately does not permit this – in any of the supported languages – because that would result in poorly structured code.
- The body of a function may consist only of the `returnreturnreturnreturnreturn` instruction – with the expression following `returnreturnreturnreturnreturn` doing all the work needed.
- More generally, the `returnreturnreturnreturnreturn` instruction will be preceded by other instructions that determine the result in several steps.
- While many languages treat functions as a procedure that returns a value, this is unhelpful. Elan enforces – for each of the supported languages – that functions are kept 'pure', like all functions used in mathematics. Specifically:
  - a function cannot undertake any input/output, or create any other side effect (i.e. change to the system that can be observed outside the function).
  - prohibited side effects including changing any of the values passed in as parameters.
  - the returned result must depend solely, and deterministically, on the values provided as parameters – just as `sqrt(2)sqrt(2)sqrt(2)sqrt(2)sqrt(2)` always produces the same result, irrespective of whatever else might be occurring in the program.

### More advanced techniques

#### Recursive function references

A function may reference itself, directly or indirectly (referencing another function that then calls back to the first one).

The same two principles discussed above under Recursive procedure calls apply equally to recursive functions.

In this example of factorial calculation, each call is on a smaller value of input, and the process stops when `nnnnn` reaches 1:

+function factorial name?(n as Int parameter definitions?) returns Int Type? 530 return (if(n > 1, n*factorial(n - 1), 1))value or expression?531 end function
+def factorial name?(n: int parameter definitions?) -> int Type?: # function 532 return (if(n > 1, n*factorial(n - 1), 1))value or expression?533 # end function
+static int Type? factorial name?(int n parameter definitions?) { // function 534 return (if(n > 1, n*factorial(n - 1), 1))value or expression?;535 } // end function
+Function factorial name?(n As Integer parameter definitions?) As Integer Type? 536 Return (if(n > 1, n*factorial(n - 1), 1))value or expression?537 End Function
+static int Type? factorial name?(int n parameter definitions?) { // function 538 return (if(n > 1, n*factorial(n - 1), 1))value or expression?;539 } // end function

## Test

### Examples of a test

Example from the Life – procedural demo. It tests all valid combinations of parameter values, because the logic of this function is quite unusual:

+test test_willLive test_name? 565 assert willLive(white, 0)actual (computed) value? is false expected value? not run 566 assert willLive(white, 1)actual (computed) value? is false expected value? not run 567 assert willLive(white, 2)actual (computed) value? is false expected value? not run 568 assert willLive(white, 3)actual (computed) value? is true expected value? not run 569 assert willLive(white, 4)actual (computed) value? is false expected value? not run 570 assert willLive(white, 5)actual (computed) value? is false expected value? not run 571 assert willLive(white, 6)actual (computed) value? is false expected value? not run 572 assert willLive(white, 7)actual (computed) value? is false expected value? not run 573 assert willLive(white, 8)actual (computed) value? is false expected value? not run 574 assert willLive(black, 0)actual (computed) value? is false expected value? not run 575 assert willLive(black, 1)actual (computed) value? is false expected value? not run 576 assert willLive(black, 2)actual (computed) value? is true expected value? not run 577 assert willLive(black, 3)actual (computed) value? is true expected value? not run 578 assert willLive(black, 4)actual (computed) value? is false expected value? not run 579 assert willLive(black, 5)actual (computed) value? is false expected value? not run 580 assert willLive(black, 6)actual (computed) value? is false expected value? not run 581 assert willLive(black, 7)actual (computed) value? is false expected value? not run 582 assert willLive(black, 8)actual (computed) value? is false expected value? not run 583 end test
+class Test_willLive(unittest.TestCase):
def test_willLive test_name?(self) -> None: 584 self.assertEqual(willLive(white, 0)actual (computed) value?, False expected value?) not run 585 self.assertEqual(willLive(white, 1)actual (computed) value?, False expected value?) not run 586 self.assertEqual(willLive(white, 2)actual (computed) value?, False expected value?) not run 587 self.assertEqual(willLive(white, 3)actual (computed) value?, True expected value?) not run 588 self.assertEqual(willLive(white, 4)actual (computed) value?, False expected value?) not run 589 self.assertEqual(willLive(white, 5)actual (computed) value?, False expected value?) not run 590 self.assertEqual(willLive(white, 6)actual (computed) value?, False expected value?) not run 591 self.assertEqual(willLive(white, 7)actual (computed) value?, False expected value?) not run 592 self.assertEqual(willLive(white, 8)actual (computed) value?, False expected value?) not run 593 self.assertEqual(willLive(black, 0)actual (computed) value?, False expected value?) not run 594 self.assertEqual(willLive(black, 1)actual (computed) value?, False expected value?) not run 595 self.assertEqual(willLive(black, 2)actual (computed) value?, True expected value?) not run 596 self.assertEqual(willLive(black, 3)actual (computed) value?, True expected value?) not run 597 self.assertEqual(willLive(black, 4)actual (computed) value?, False expected value?) not run 598 self.assertEqual(willLive(black, 5)actual (computed) value?, False expected value?) not run 599 self.assertEqual(willLive(black, 6)actual (computed) value?, False expected value?) not run 600 self.assertEqual(willLive(black, 7)actual (computed) value?, False expected value?) not run 601 self.assertEqual(willLive(black, 8)actual (computed) value?, False expected value?) not run 602 # end test
+[TestClass] class Test_willLive
[TestMethod] static void test_willLive test_name?() { 603 Assert.AreEqual(false expected value?, willLive(white, 0)actual (computed) value?); not run 604 Assert.AreEqual(false expected value?, willLive(white, 1)actual (computed) value?); not run 605 Assert.AreEqual(false expected value?, willLive(white, 2)actual (computed) value?); not run 606 Assert.AreEqual(true expected value?, willLive(white, 3)actual (computed) value?); not run 607 Assert.AreEqual(false expected value?, willLive(white, 4)actual (computed) value?); not run 608 Assert.AreEqual(false expected value?, willLive(white, 5)actual (computed) value?); not run 609 Assert.AreEqual(false expected value?, willLive(white, 6)actual (computed) value?); not run 610 Assert.AreEqual(false expected value?, willLive(white, 7)actual (computed) value?); not run 611 Assert.AreEqual(false expected value?, willLive(white, 8)actual (computed) value?); not run 612 Assert.AreEqual(false expected value?, willLive(black, 0)actual (computed) value?); not run 613 Assert.AreEqual(false expected value?, willLive(black, 1)actual (computed) value?); not run 614 Assert.AreEqual(true expected value?, willLive(black, 2)actual (computed) value?); not run 615 Assert.AreEqual(true expected value?, willLive(black, 3)actual (computed) value?); not run 616 Assert.AreEqual(false expected value?, willLive(black, 4)actual (computed) value?); not run 617 Assert.AreEqual(false expected value?, willLive(black, 5)actual (computed) value?); not run 618 Assert.AreEqual(false expected value?, willLive(black, 6)actual (computed) value?); not run 619 Assert.AreEqual(false expected value?, willLive(black, 7)actual (computed) value?); not run 620 Assert.AreEqual(false expected value?, willLive(black, 8)actual (computed) value?); not run 621 }} // end test
+<TestClass Class Test_willLive
<TestMethod> Sub test_willLive test_name?() 622 Assert.AreEqual(False expected value?, willLive(white, 0)actual (computed) value?) not run 623 Assert.AreEqual(False expected value?, willLive(white, 1)actual (computed) value?) not run 624 Assert.AreEqual(False expected value?, willLive(white, 2)actual (computed) value?) not run 625 Assert.AreEqual(True expected value?, willLive(white, 3)actual (computed) value?) not run 626 Assert.AreEqual(False expected value?, willLive(white, 4)actual (computed) value?) not run 627 Assert.AreEqual(False expected value?, willLive(white, 5)actual (computed) value?) not run 628 Assert.AreEqual(False expected value?, willLive(white, 6)actual (computed) value?) not run 629 Assert.AreEqual(False expected value?, willLive(white, 7)actual (computed) value?) not run 630 Assert.AreEqual(False expected value?, willLive(white, 8)actual (computed) value?) not run 631 Assert.AreEqual(False expected value?, willLive(black, 0)actual (computed) value?) not run 632 Assert.AreEqual(False expected value?, willLive(black, 1)actual (computed) value?) not run 633 Assert.AreEqual(True expected value?, willLive(black, 2)actual (computed) value?) not run 634 Assert.AreEqual(True expected value?, willLive(black, 3)actual (computed) value?) not run 635 Assert.AreEqual(False expected value?, willLive(black, 4)actual (computed) value?) not run 636 Assert.AreEqual(False expected value?, willLive(black, 5)actual (computed) value?) not run 637 Assert.AreEqual(False expected value?, willLive(black, 6)actual (computed) value?) not run 638 Assert.AreEqual(False expected value?, willLive(black, 7)actual (computed) value?) not run 639 Assert.AreEqual(False expected value?, willLive(black, 8)actual (computed) value?) not run 640 End Sub
End Class
+class Test_willLive {
@Test static void test_willLive test_name?() { 641 assertEquals(false expected value?, willLive(white, 0)actual (computed) value?); not run 642 assertEquals(false expected value?, willLive(white, 1)actual (computed) value?); not run 643 assertEquals(false expected value?, willLive(white, 2)actual (computed) value?); not run 644 assertEquals(true expected value?, willLive(white, 3)actual (computed) value?); not run 645 assertEquals(false expected value?, willLive(white, 4)actual (computed) value?); not run 646 assertEquals(false expected value?, willLive(white, 5)actual (computed) value?); not run 647 assertEquals(false expected value?, willLive(white, 6)actual (computed) value?); not run 648 assertEquals(false expected value?, willLive(white, 7)actual (computed) value?); not run 649 assertEquals(false expected value?, willLive(white, 8)actual (computed) value?); not run 650 assertEquals(false expected value?, willLive(black, 0)actual (computed) value?); not run 651 assertEquals(false expected value?, willLive(black, 1)actual (computed) value?); not run 652 assertEquals(true expected value?, willLive(black, 2)actual (computed) value?); not run 653 assertEquals(true expected value?, willLive(black, 3)actual (computed) value?); not run 654 assertEquals(false expected value?, willLive(black, 4)actual (computed) value?); not run 655 assertEquals(false expected value?, willLive(black, 5)actual (computed) value?); not run 656 assertEquals(false expected value?, willLive(black, 6)actual (computed) value?); not run 657 assertEquals(false expected value?, willLive(black, 7)actual (computed) value?); not run 658 assertEquals(false expected value?, willLive(black, 8)actual (computed) value?); not run 659 }} // end test

Example from the Snake – procedural demo, showing the use of a variable to create data to be used within multiple assertions:

+test test_getAdjacentSquare test_name? 660 variable sq name? set to [20, 15]value or expression?661 assert getAdjacentSquare(sq, Direction.up)actual (computed) value? is [20, 14]expected value? not run 662 assert getAdjacentSquare(sq, Direction.down)actual (computed) value? is [20, 16]expected value? not run 663 assert getAdjacentSquare(sq, Direction.left)actual (computed) value? is [19, 15]expected value? not run 664 assert getAdjacentSquare(sq, Direction.right)actual (computed) value? is [21, 15]expected value? not run 665 # boundary comment? assert getAdjacentSquare([0, 15], Direction.left)actual (computed) value? is [-1, 15]expected value? not run 666 end test
+class Test_getAdjacentSquare(unittest.TestCase):
def test_getAdjacentSquare test_name?(self) -> None: 667 sq name? = [20, 15]value or expression? # variable definition 668 self.assertEqual(getAdjacentSquare(sq, Direction.up)actual (computed) value?, [20, 14]expected value?) not run 669 self.assertEqual(getAdjacentSquare(sq, Direction.down)actual (computed) value?, [20, 16]expected value?) not run 670 self.assertEqual(getAdjacentSquare(sq, Direction.left)actual (computed) value?, [19, 15]expected value?) not run 671 self.assertEqual(getAdjacentSquare(sq, Direction.right)actual (computed) value?, [21, 15]expected value?) not run 672 # boundary comment? self.assertEqual(getAdjacentSquare([0, 15], Direction.left)actual (computed) value?, [-1, 15]expected value?) not run 673 # end test
+[TestClass] class Test_getAdjacentSquare
[TestMethod] static void test_getAdjacentSquare test_name?() { 674 var sq name? = new [] {20, 15}value or expression?;675 Assert.AreEqual(new [] {20, 14}expected value?, getAdjacentSquare(sq, Direction.up)actual (computed) value?); not run 676 Assert.AreEqual(new [] {20, 16}expected value?, getAdjacentSquare(sq, Direction.down)actual (computed) value?); not run 677 Assert.AreEqual(new [] {19, 15}expected value?, getAdjacentSquare(sq, Direction.left)actual (computed) value?); not run 678 Assert.AreEqual(new [] {21, 15}expected value?, getAdjacentSquare(sq, Direction.right)actual (computed) value?); not run 679 // boundary comment? Assert.AreEqual(new [] {-1, 15}expected value?, getAdjacentSquare(new [] {0, 15}, Direction.left)actual (computed) value?); not run 680 }} // end test
+<TestClass Class Test_getAdjacentSquare
<TestMethod> Sub test_getAdjacentSquare test_name?() 681 Dim sq name? = {20, 15}value or expression? ' variable definition 682 Assert.AreEqual({20, 14}expected value?, getAdjacentSquare(sq, Direction.up)actual (computed) value?) not run 683 Assert.AreEqual({20, 16}expected value?, getAdjacentSquare(sq, Direction.down)actual (computed) value?) not run 684 Assert.AreEqual({19, 15}expected value?, getAdjacentSquare(sq, Direction.left)actual (computed) value?) not run 685 Assert.AreEqual({21, 15}expected value?, getAdjacentSquare(sq, Direction.right)actual (computed) value?) not run 686 ' boundary comment? Assert.AreEqual({-1, 15}expected value?, getAdjacentSquare({0, 15}, Direction.left)actual (computed) value?) not run 687 End Sub
End Class
+class Test_getAdjacentSquare {
@Test static void test_getAdjacentSquare test_name?() { 688 var sq name? = list(20, 15)value or expression?;689 assertEquals(list(20, 14)expected value?, getAdjacentSquare(sq, Direction.up)actual (computed) value?); not run 690 assertEquals(list(20, 16)expected value?, getAdjacentSquare(sq, Direction.down)actual (computed) value?); not run 691 assertEquals(list(19, 15)expected value?, getAdjacentSquare(sq, Direction.left)actual (computed) value?); not run 692 assertEquals(list(21, 15)expected value?, getAdjacentSquare(sq, Direction.right)actual (computed) value?); not run 693 // boundary comment? assertEquals(list(-1, 15)expected value?, getAdjacentSquare(list(0, 15), Direction.left)actual (computed) value?); not run 694 }} // end test

### What you need to know about a test

- The form of automated testing provided by Elan (for all of the supported languages) are known as 'unit testing'.
- Some languages allow unit tests to be applied to procedures, but this is dangerous since running the tests could result in unwanted damage to the system (such as writing to a database). Elan guarantees that tests are safe by restricting them to functions.
- A test method must be given a name that starts with the prefix `test_` (automatically supplied) and followed, typically, by the name of the function.
- Tests are always written at global level in Elan, but they may be anywhere within the file: you could write a test adjacent to the function being tested, or group all the tests at the end of the file.
- A test method may define variables for use in the test – for example to define a data value that will be used in several `assertassertassertassertassert` instructions.
- A test method must include at least one `assertassertassertassertassert` instruction – with each one typically covering a different use case.
- Each `assertassertassertassertassert` instruction must have two fields:
  1. the actual (i.e. computed) value – which usually consists of a call to the function being tested, with specific arguments,
  2. the expected result.
- The tests do not form part of the executable program: you cannot call a test from within other code.
- Instead, all tests in a program are run automatically, each time the code compiles.
- The result is shown alongside each `assertassertassertassertassert` instruction, and the overall summary is shown in the status panel at the top centre of the Elan IDE.
- Writing tests for every function is good practice: they confirm that your function implementations are correct, not only when you write them, but every time you reload the program from file or make changes.
- Tests also encourage you to 're-factor', improve, or extend the capability of your functions without fear that you inadvertently make then incorrect for certain cases.

### More advanced techniques

#### Ghosting tests

To prevent a particular test from running, you can use `ghostingghostingghostingghostingghosting` .

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

You can ghost 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
+class Test_overApple(unittest.TestCase):
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 # end test
+[TestClass] class Test_overApple
[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 }} // end test
+<TestClass Class Test_overApple
<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
End Class
+class Test_overApple {
@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 }} // end test

or you can ghost individual asserts:

+test test_overApple test_name? 695 variable g1 name? set to new Game(new Random())value or expression?696 variable g2 name? set to g1.withApple(new Square(23, 15))value or expression?697 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?698 assert headOverApple(g3)actual (computed) value? is true expected value? not run 699 end test
+class Test_overApple(unittest.TestCase):
def test_overApple test_name?(self) -> None: 700 g1 name? = Game(Random())value or expression? # variable definition 701 g2 name? = g1.withApple(Square(23, 15))value or expression? # variable definition 702 self.assertEqual(headOverApple(g2)actual (computed) value?, True expected value?) not run g3 name? = g2.withHead(Square(23, 15))value or expression? # variable definition 703 self.assertEqual(headOverApple(g3)actual (computed) value?, True expected value?) not run 704 # end test
+[TestClass] class Test_overApple
[TestMethod] static void test_overApple test_name?() { 705 var g1 name? = new Game(new Random())value or expression?;706 var g2 name? = g1.withApple(new Square(23, 15))value or expression?;707 Assert.AreEqual(true expected value?, headOverApple(g2)actual (computed) value?); not run var g3 name? = g2.withHead(new Square(23, 15))value or expression?;708 Assert.AreEqual(true expected value?, headOverApple(g3)actual (computed) value?); not run 709 }} // end test
+<TestClass Class Test_overApple
<TestMethod> Sub test_overApple test_name?() 710 Dim g1 name? = New Game(New Random())value or expression? ' variable definition 711 Dim g2 name? = g1.withApple(New Square(23, 15))value or expression? ' variable definition 712 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 713 Assert.AreEqual(True expected value?, headOverApple(g3)actual (computed) value?) not run 714 End Sub
End Class
+class Test_overApple {
@Test static void test_overApple test_name?() { 715 var g1 name? = new Game(new Random())value or expression?;716 var g2 name? = g1.withApple(new Square(23, 15))value or expression?;717 assertEquals(true expected value?, headOverApple(g2)actual (computed) value?); not run var g3 name? = g2.withHead(new Square(23, 15))value or expression?;718 assertEquals(true expected value?, headOverApple(g3)actual (computed) value?); not run 719 }} // end test

#### Testing `FloatfloatdoubleDoubledouble` values

When testing `FloatfloatdoubleDoubledouble` values it is recommend that you use method round 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? 720 assert sqrt(2).round(3)actual (computed) value? is 1.414 expected value? not run 721 end test
+class Test_round(unittest.TestCase):
def test_round test_name?(self) -> None: 722 self.assertEqual(sqrt(2).round(3)actual (computed) value?, 1.414 expected value?) not run 723 # end test
+[TestClass] class Test_round
[TestMethod] static void test_round test_name?() { 724 Assert.AreEqual(1.414 expected value?, sqrt(2).round(3)actual (computed) value?); not run 725 }} // end test
+<TestClass Class Test_round
<TestMethod> Sub test_round test_name?() 726 Assert.AreEqual(1.414 expected value?, sqrt(2).round(3)actual (computed) value?) not run 727 End Sub
End Class
+class Test_round {
@Test static void test_round test_name?() { 728 assertEquals(1.414 expected value?, sqrt(2).round(3)actual (computed) value?); not run 729 }} // end test

#### Testing for runtime errors

If the expression you are testing causes 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.

This assert statement shows how to test for an expected error message:

+test test_message test_name? 730 variable a name? set to [5, 1, 7]value or expression?731 assert a[4]actual (computed) value? is 0 expected value? not run 732 assert a[4]actual (computed) value? is "Out of range index: 4 size: 3"expected value? not run 733 end test
+class Test_message(unittest.TestCase):
def test_message test_name?(self) -> None: 734 a name? = [5, 1, 7]value or expression? # variable definition 735 self.assertEqual(a[4]actual (computed) value?, 0 expected value?) not run 736 self.assertEqual(a[4]actual (computed) value?, "Out of range index: 4 size: 3"expected value?) not run 737 # end test
+[TestClass] class Test_message
[TestMethod] static void test_message test_name?() { 738 var a name? = new [] {5, 1, 7}value or expression?;739 Assert.AreEqual(0 expected value?, a[4]actual (computed) value?); not run 740 Assert.AreEqual("Out of range index: 4 size: 3"expected value?, a[4]actual (computed) value?); not run 741 }} // end test
+<TestClass Class Test_message
<TestMethod> Sub test_message test_name?() 742 Dim a name? = {5, 1, 7}value or expression? ' variable definition 743 Assert.AreEqual(0 expected value?, a(4)actual (computed) value?) not run 744 Assert.AreEqual("Out of range index: 4 size: 3"expected value?, a(4)actual (computed) value?) not run 745 End Sub
End Class
+class Test_message {
@Test static void test_message test_name?() { 746 var a name? = list(5, 1, 7)value or expression?;747 assertEquals(0 expected value?, a[4]actual (computed) value?); not run 748 assertEquals("Out of range index: 4 size: 3"expected value?, a[4]actual (computed) value?); not run 749 }} // end 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. In the following example, the programmer has accidentally missed out the `/` in the closing Html tag:

+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?750
+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 751
+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?;752
+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?753
+static 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 754

#### 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 test.

## Constant

### Examples of a constant

From the Turtle Snowflake demo. The constant value `sidesidesidesideside` is defined like this:

+constant side name? set to 100 literal value or data structure?755
+side name? = 100 literal value or data structure? # constant 756
+const Int side name? = 100 literal value or data structure?;757
+Const side name? = 100 literal value or data structure?758
+static final Int side name? = 100 literal value or data structure?; // constant 759

and used within the main routine as an argument to pass into the drawSide procedure:

call drawSide procedureName?(side, t arguments?)760
drawSide procedureName?(side, t arguments?) # procedure call 761
drawSide procedureName?(side, t arguments?); // procedure call 762
drawSide procedureName?(side, t arguments?) ' procedure call 763
drawSide procedureName?(side, t arguments?); // procedure call 764

Here are some other examples of globally fixed values that can be referred to from anywhere in your program:

+constant maxHits name? set to 10 literal value or data structure?765
+maxHits name? = 10 literal value or data structure? # constant 766
+const Int maxHits name? = 10 literal value or data structure?;767
+Const maxHits name? = 10 literal value or data structure?768
+static final Int maxHits name? = 10 literal value or data structure?; // constant 769

### What you need to know about a constant

- A constant is a named value that never changes while a program is running.
- The Elan library defines a few constants including `pipipipipi` and a handful of simple colours e.g. `redredredredred`.
- The constant instruction allows you to define your own constants.
- Even though Python does not natively support the idea of a constant, when writing Python with Elan, having created a constant with constant instruction you will find that you cannot change it with a assignment instruction.
- When coding with Elan, a constant:
  - may be defined only at global (file) level,
  - must be given a unique name, starting lower case (`sidesidesidesideside` above),
  - must be defined by a literal value, which must be a number, string, or Boolean (i.e. true or false).
- If you define your own constant with the same name as a library constant, you will not be able to access the library one within your program.

### More advanced techniques

#### Constant data structures

To set up a data structure that is to be a constant in your program, you define it as the value returned by a function that requires no parameters. Such a function can then be referenced from anywhere in the program, often from within an expression, remembering to add empty brackets after its name.

The following examples define a constant list of colours (using numerical hex values), and a constant dictionary that specifies the colour for each suit in a deck of cards using system method createDectionary to set up the dictionary from a list of 2-tuples. In this second case, integer ouput is converted to a string of hexadecimal before printing by using example function hex:

+main 770 print($"{rainbow()[0]} (dec) is violet"arguments?)771 print($"{hex(suitColours()["hearts"])} (hex) is red"arguments?)772 end main
+def main() -> None: 773 print(f"{rainbow()[0]} (dec) is violet"arguments?)774 print(f"{hex(suitColours()["hearts"])} (hex) is red"arguments?)775 # end main
+static void main() { 776 Console.WriteLine($"{rainbow()[0]} (dec) is violet"arguments?); // print statement 777 Console.WriteLine($"{hex(suitColours()["hearts"])} (hex) is red"arguments?); // print statement 778 } // end main
+Sub main() 779 Console.WriteLine($"{rainbow()(0)} (dec) is violet"arguments?) ' print statement 780 Console.WriteLine($"{hex(suitColours()("hearts"))} (hex) is red"arguments?) ' print statement 781 End Sub
+static void main() { 782 System.out.println(String.format("% (dec) is violet", rainbow()[0])arguments?); // print statement 783 System.out.println(String.format("% (hex) is red", hex(suitColours()["hearts"]))arguments?); // print statement 784 } // end main

## Enum

### Examples of an enum

From the Snake – procedural demo, this `enumenumenumenumenum` is defined:

enum Direction Name? up, down, left, right values?values?785
class Direction Name?(Enum):
up = 1
down = 2
left = 3
right = 4 values?786
enum Direction Name? {up, down, left, right values?values?}787
Enum Direction Name?
up = 0
down = 1
left = 2
right = 3
End Enum values?788
enum Direction Name? {up, down, left, right values?values?}789

It is used in several places in the code, for example:

+function getAdjacentSquare name?(sq as List<of Int>, dir as Direction parameter definitions?) returns List<of Int>Type? 790 variable newX name? set to sq[0]value or expression?791 variable newY name? set to sq[1]value or expression?792 +if dir is Direction.left condition? then 793 assign newX variableName? to newX - 1 value or expression?794 elif dir is Direction.right condition? then 795 assign newX variableName? to newX + 1 value or expression?796 elif dir is Direction.up condition? then 797 assign newY variableName? to newY - 1 value or expression?798 elif dir is Direction.down condition? then 799 assign newY variableName? to newY + 1 value or expression?800 end if return [newX, newY]value or expression?801 end function
+def getAdjacentSquare name?(sq: list[int], dir: Direction parameter definitions?) -> list[int]Type?: # function 802 newX name? = sq[0]value or expression? # variable definition 803 newY name? = sq[1]value or expression? # variable definition 804 +if dir == Direction.left condition?: 805 newX variableName? = newX - 1 value or expression? # assignment 806 elif dir == Direction.right condition?: # else if 807 newX variableName? = newX + 1 value or expression? # assignment 808 elif dir == Direction.up condition?: # else if 809 newY variableName? = newY - 1 value or expression? # assignment 810 elif dir == Direction.down condition?: # else if 811 newY variableName? = newY + 1 value or expression? # assignment 812 # end if return [newX, newY]value or expression?813 # end function
+static List<int>Type? getAdjacentSquare name?(List<int> sq, Direction dir parameter definitions?) { // function 814 var newX name? = sq[0]value or expression?;815 var newY name? = sq[1]value or expression?;816 +if (dir == Direction.left condition?) { 817 newX variableName? = newX - 1 value or expression?; // assignment 818 } else if (dir == Direction.right condition?) {819 newX variableName? = newX + 1 value or expression?; // assignment 820 } else if (dir == Direction.up condition?) {821 newY variableName? = newY - 1 value or expression?; // assignment 822 } else if (dir == Direction.down condition?) {823 newY variableName? = newY + 1 value or expression?; // assignment 824 } // end if return new [] {newX, newY}value or expression?;825 } // end function
+Function getAdjacentSquare name?(sq As List(Of Integer), dir As Direction parameter definitions?) As List(Of Integer)Type? 826 Dim newX name? = sq(0)value or expression? ' variable definition 827 Dim newY name? = sq(1)value or expression? ' variable definition 828 +If dir = Direction.left condition? Then 829 newX variableName? = newX - 1 value or expression? ' assignment 830 ElseIf dir = Direction.right condition? Then 831 newX variableName? = newX + 1 value or expression? ' assignment 832 ElseIf dir = Direction.up condition? Then 833 newY variableName? = newY - 1 value or expression? ' assignment 834 ElseIf dir = Direction.down condition? Then 835 newY variableName? = newY + 1 value or expression? ' assignment 836 End If Return {newX, newY}value or expression?837 End Function
+static List<int>Type? getAdjacentSquare name?(List<int> sq, Direction dir parameter definitions?) { // function 838 var newX name? = sq[0]value or expression?;839 var newY name? = sq[1]value or expression?;840 +if (dir == Direction.left condition?) { 841 newX variableName? = newX - 1 value or expression?; // assignment 842 } else if (dir == Direction.right condition?) {843 newX variableName? = newX + 1 value or expression?; // assignment 844 } else if (dir == Direction.up condition?) {845 newY variableName? = newY - 1 value or expression?; // assignment 846 } else if (dir == Direction.down condition?) {847 newY variableName? = newY + 1 value or expression?; // assignment 848 } // end if return list(newX, newY)value or expression?;849 } // end function

From the Blackjack demo:

enum Suit Name? spades, hearts, diamonds, clubs values?values?850
class Suit Name?(Enum):
spades = 1
hearts = 2
diamonds = 3
clubs = 4 values?851
enum Suit Name? {spades, hearts, diamonds, clubs values?values?}852
Enum Suit Name?
spades = 0
hearts = 1
diamonds = 2
clubs = 3
End Enum values?853
enum Suit Name? {spades, hearts, diamonds, clubs values?values?}854

### What you need to know about an enum

- An enum – short for 'enumeration' – is the simplest form of user-defined type.

- Because it is a type, the name given to the enum (e.g. `DirectionDirectionDirectionDirectionDirection` above) must start with an upper case letter.
- An enum forces any named value of that type to be one of the fixed number of named values listed in the enum definition.
- The instruction
  variable currentDir name? set to Direction.right value or expression?855
  currentDir name? = Direction.right value or expression? # variable definition 856
  var currentDir name? = Direction.right value or expression?;857
  Dim currentDir name? = Direction.right value or expression? ' variable definition 858
  var currentDir name? = Direction.right value or expression?;859
  initialises `currentDircurrentDircurrentDircurrentDircurrentDir` with the value `rightrightrightrightright` which is valid only because it is listed in the definition of the enum named `DirectionDirectionDirectionDirectionDirection`.
- Because the variable `currentDirectcurrentDirectcurrentDirectcurrentDirectcurrentDirect` has the type `DirectionDirectionDirectionDirectionDirection`, it may only be assigned to another of the values defined in enum `DirectionDirectionDirectionDirectionDirection`
- An enum value cannot be converted to anything else.
- The advantages of using enums are:
  - readability,
  - safety, because if the four directions were defined as strings, e.g. `"right""right""right""right""right"` a mis-spelling might not be picked up until runtime. Whereas with the enum, writing `Direction.rihgtDirection.rihgtDirection.rihgtDirection.rihgtDirection.rihgt` would raise an error at compilation.

## Comment

### Examples of a comment

From the Snake – procedural demo, where a comment at global level describes how to use the program:

# Use the w,a,s,d keys to change snake's direction comment?
// Use the w,a,s,d keys to change snake's direction comment?
' Use the w,a,s,d keys to change snake's direction comment?
// Use the w,a,s,d keys to change snake's direction comment?

From the Bubbles demo, where comments explain specific blocks of instructions

+procedure moveGrowBurst name?(bubbles as List<of CircleVG>parameter definitions?) 860 +for b item? in bubbles source? 861 +if random() < 0.05 condition? then 862 # 5% chance bubble 'bursts' and starts again tiny at bottom comment? call b.setRadius procedureName?(0 arguments?)863 call b.setCentreY procedureName?(75 arguments?)864 else 865 # bubble rises and grows slightly comment? call b.setCentreY procedureName?(b.centreY - 1 arguments?)866 call b.setRadius procedureName?(b.radius + 0.2 arguments?)867 end if end for call displayVectorGraphics procedureName?(bubbles arguments?)868 call sleep_ms procedureName?(5 arguments?)869 end procedure
+def moveGrowBurst name?(bubbles: list[CircleVG]parameter definitions?) -> None: # procedure 870 +for b item? in bubbles source?: 871 +if random() < 0.05 condition?: 872 # 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?) # procedure call 873 b.setCentreY procedureName?(75 arguments?) # procedure call 874 else:875 # bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?) # procedure call 876 b.setRadius procedureName?(b.radius + 0.2 arguments?) # procedure call 877 # end if # end for displayVectorGraphics procedureName?(bubbles arguments?) # procedure call 878 sleep_ms procedureName?(5 arguments?) # procedure call 879 # end procedure
+static void moveGrowBurst name?(List<CircleVG> bubbles parameter definitions?) { // procedure 880 +foreach (var b item? in bubbles source?) { 881 +if (random() < 0.05 condition?) { 882 // 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?); // procedure call 883 b.setCentreY procedureName?(75 arguments?); // procedure call 884 } else {885 // bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?); // procedure call 886 b.setRadius procedureName?(b.radius + 0.2 arguments?); // procedure call 887 } // end if } // end foreach displayVectorGraphics procedureName?(bubbles arguments?); // procedure call 888 sleep_ms procedureName?(5 arguments?); // procedure call 889 } // end procedure
+Sub moveGrowBurst name?(bubbles As List(Of CircleVG)parameter definitions?) ' procedure 890 +For Each b item? In bubbles source? 891 +If random() < 0.05 condition? Then 892 ' 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?) ' procedure call 893 b.setCentreY procedureName?(75 arguments?) ' procedure call 894 Else 895 ' bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?) ' procedure call 896 b.setRadius procedureName?(b.radius + 0.2 arguments?) ' procedure call 897 End If Next b displayVectorGraphics procedureName?(bubbles arguments?) ' procedure call 898 sleep_ms procedureName?(5 arguments?) ' procedure call 899 End Sub
+static void moveGrowBurst name?(List<CircleVG> bubbles parameter definitions?) { // procedure 900 +foreach (var b item? in bubbles source?) { 901 +if (random() < 0.05 condition?) { 902 // 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?); // procedure call 903 b.setCentreY procedureName?(75 arguments?); // procedure call 904 } else {905 // bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?); // procedure call 906 b.setRadius procedureName?(b.radius + 0.2 arguments?); // procedure call 907 } // end if } // end foreach displayVectorGraphics procedureName?(bubbles arguments?); // procedure call 908 sleep_ms procedureName?(5 arguments?); // procedure call 909 } // end procedure

### What you need to know about a 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 may be entered at any new code prompt by typing the symbol `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.` 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 [.
- When coding with Elan, a comment is always on a line of its own.
- Comments that you see written on the same line as and after an instruction are generated by the system and may not be edited or deleted.
- 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 you. This comment is known as the 'file header'.

# Statement instructions

Statement instructions (sometimes referred to as 'statements') are the instructions used with in the methods of a program: the main routine, functions, and procedures.

## Print

### Examples of a print statement

From the Date Time demo, printing the time (as a number of seconds) and then the date by calling the function getDate inline within the print instruction:

+main 910 variable reply name? set to ""value or expression?911 +while not reply.upperCase().equals("Q")condition? 912 assign reply variableName? to input("RETURN for time now or Unix time (positive integer) or Q to quit")value or expression?913 +if reply.equals("")condition? then 914 variable now name? set to divAsInt(clock(), 1000)value or expression?915 print(now arguments?)916 print(getDate(now)arguments?)917 else 918 +try 919 variable td name? set to int(reply)value or expression?920 +if td >= 0 condition? then 921 print(getDate(td)arguments?)922 end if catch e variableName? as ElanRuntimeError type e.g. ElanRuntimeError or CustomError?923 end try end if end while end main
+def main() -> None: 924 reply name? = ""value or expression? # variable definition 925 +while not reply.upperCase().equals("Q")condition?: 926 reply variableName? = input("RETURN for time now or Unix time (positive integer) or Q to quit")value or expression? # assignment 927 +if reply.equals("")condition?: 928 now name? = divAsInt(clock(), 1000)value or expression? # variable definition 929 print(now arguments?)930 print(getDate(now)arguments?)931 else:932 +try: 933 td name? = int(reply)value or expression? # variable definition 934 +if td >= 0 condition?: 935 print(getDate(td)arguments?)936 # end if except ElanRuntimeError type e.g. ElanRuntimeError or CustomError? as e variableName?: # catch 937 # end try # end if # end while # end main
+static void main() { 938 var reply name? = ""value or expression?;939 +while (!reply.upperCase().equals("Q")condition?) { 940 reply variableName? = input("RETURN for time now or Unix time (positive integer) or Q to quit")value or expression?; // assignment 941 +if (reply.equals("")condition?) { 942 var now name? = divAsInt(clock(), 1000)value or expression?;943 Console.WriteLine(now arguments?); // print statement 944 Console.WriteLine(getDate(now)arguments?); // print statement 945 } else {946 +try { 947 var td name? = int(reply)value or expression?;948 +if (td >= 0 condition?) { 949 Console.WriteLine(getDate(td)arguments?); // print statement 950 } // end if } catch (ElanRuntimeError type e.g. ElanRuntimeError or CustomError? e variableName?) {951 } // end try } // end if } // end while } // end main
+Sub main() 952 Dim reply name? = ""value or expression? ' variable definition 953 +While Not reply.upperCase().equals("Q")condition? 954 reply variableName? = input("RETURN for time now or Unix time (positive integer) or Q to quit")value or expression? ' assignment 955 +If reply.equals("")condition? Then 956 Dim now name? = divAsInt(clock(), 1000)value or expression? ' variable definition 957 Console.WriteLine(now arguments?) ' print statement 958 Console.WriteLine(getDate(now)arguments?) ' print statement 959 Else 960 +Try 961 Dim td name? = int(reply)value or expression? ' variable definition 962 +If td >= 0 condition? Then 963 Console.WriteLine(getDate(td)arguments?) ' print statement 964 End If Catch e variableName? As ElanRuntimeError type e.g. ElanRuntimeError or CustomError?965 End Try End If End While End Sub
+static void main() { 966 var reply name? = ""value or expression?;967 +while (!reply.upperCase().equals("Q")condition?) { 968 reply variableName? = input("RETURN for time now or Unix time (positive integer) or Q to quit")value or expression?; // assignment 969 +if (reply.equals("")condition?) { 970 var now name? = divAsInt(clock(), 1000)value or expression?;971 System.out.println(now arguments?); // print statement 972 System.out.println(getDate(now)arguments?); // print statement 973 } else {974 +try { 975 var td name? = int(reply)value or expression?;976 +if (td >= 0 condition?) { 977 System.out.println(getDate(td)arguments?); // print statement 978 } // end if } catch (ElanRuntimeError type e.g. ElanRuntimeError or CustomError? e variableName?) {979 } // end try } // end if } // end while } // end main

From the Ripple sort demo, printing a list:

+main 980 variable li name? set to [7, 1, 0, 4, 8, 3, 6]value or expression?981 print(li arguments?)982 call inPlaceRippleSort procedureName?(li arguments?)983 print(li arguments?)984 end main
+def main() -> None: 985 li name? = [7, 1, 0, 4, 8, 3, 6]value or expression? # variable definition 986 print(li arguments?)987 inPlaceRippleSort procedureName?(li arguments?) # procedure call 988 print(li arguments?)989 # end main
+static void main() { 990 var li name? = new [] {7, 1, 0, 4, 8, 3, 6}value or expression?;991 Console.WriteLine(li arguments?); // print statement 992 inPlaceRippleSort procedureName?(li arguments?); // procedure call 993 Console.WriteLine(li arguments?); // print statement 994 } // end main
+Sub main() 995 Dim li name? = {7, 1, 0, 4, 8, 3, 6}value or expression? ' variable definition 996 Console.WriteLine(li arguments?) ' print statement 997 inPlaceRippleSort procedureName?(li arguments?) ' procedure call 998 Console.WriteLine(li arguments?) ' print statement 999 End Sub
+static void main() { 1000 var li name? = list(7, 1, 0, 4, 8, 3, 6)value or expression?;1001 System.out.println(li arguments?); // print statement 1002 inPlaceRippleSort procedureName?(li arguments?); // procedure call 1003 System.out.println(li arguments?); // print statement 1004 } // end main

From the Snake – procedural demo, printing an interpolated string (last line of the main routine):

+main 1005 variable blocks name? set to createBlockGraphics(white)value or expression?1006 variable head name? set to [20, 15]value or expression?1007 variable tail name? set to head value or expression?1008 variable body name? set to [head]value or expression?1009 variable currentDir name? set to Direction.right value or expression?1010 variable gameOn name? set to true value or expression?1011 variable apple name? set to [0, 0]value or expression?1012 call setAppleToRandomPosition procedureName?(apple, body arguments?)1013 +while gameOn condition? 1014 call updateDisplay procedureName?(blocks, head, tail, body, apple arguments?)1015 variable currentDirRef name? set to new AsRef<of Direction>(currentDir)value or expression?1016 variable headRef name? set to new AsRef<of List<of Int>>(head)value or expression?1017 variable tailRef name? set to new AsRef<of List<of Int>>(tail)value or expression?1018 call updateSnake procedureName?(currentDirRef, tailRef, headRef, body arguments?)1019 assign head variableName? to headRef.value()value or expression?1020 assign tail variableName? to tailRef.value()value or expression?1021 assign currentDir variableName? to currentDirRef.value()value or expression?1022 assign gameOn variableName? to not hasHitEdge(head[0], head[1]) and not body.contains(head)value or expression?1023 +if head.equals(apple)condition? then 1024 call setAppleToRandomPosition procedureName?(apple, body arguments?)1025 else 1026 call body.removeAt procedureName?(0 arguments?)1027 end if call sleep_ms procedureName?(150 arguments?)1028 end while print($"Game Over! Score: {body.length() - 1}"arguments?)1029 end main
+def main() -> None: 1030 blocks name? = createBlockGraphics(white)value or expression? # variable definition 1031 head name? = [20, 15]value or expression? # variable definition 1032 tail name? = head value or expression? # variable definition 1033 body name? = [head]value or expression? # variable definition 1034 currentDir name? = Direction.right value or expression? # variable definition 1035 gameOn name? = True value or expression? # variable definition 1036 apple name? = [0, 0]value or expression? # variable definition 1037 setAppleToRandomPosition procedureName?(apple, body arguments?) # procedure call 1038 +while gameOn condition?: 1039 updateDisplay procedureName?(blocks, head, tail, body, apple arguments?) # procedure call 1040 currentDirRef name? = AsRef[Direction](currentDir)value or expression? # variable definition 1041 headRef name? = AsRef[list[int]](head)value or expression? # variable definition 1042 tailRef name? = AsRef[list[int]](tail)value or expression? # variable definition 1043 updateSnake procedureName?(currentDirRef, tailRef, headRef, body arguments?) # procedure call 1044 head variableName? = headRef.value()value or expression? # assignment 1045 tail variableName? = tailRef.value()value or expression? # assignment 1046 currentDir variableName? = currentDirRef.value()value or expression? # assignment 1047 gameOn variableName? = not hasHitEdge(head[0], head[1]) and not body.contains(head)value or expression? # assignment 1048 +if head.equals(apple)condition?: 1049 setAppleToRandomPosition procedureName?(apple, body arguments?) # procedure call 1050 else:1051 body.removeAt procedureName?(0 arguments?) # procedure call 1052 # end if sleep_ms procedureName?(150 arguments?) # procedure call 1053 # end while print(f"Game Over! Score: {body.length() - 1}"arguments?)1054 # end main
+static void main() { 1055 var blocks name? = createBlockGraphics(white)value or expression?;1056 var head name? = new [] {20, 15}value or expression?;1057 var tail name? = head value or expression?;1058 var body name? = new [] {head}value or expression?;1059 var currentDir name? = Direction.right value or expression?;1060 var gameOn name? = true value or expression?;1061 var apple name? = new [] {0, 0}value or expression?;1062 setAppleToRandomPosition procedureName?(apple, body arguments?); // procedure call 1063 +while (gameOn condition?) { 1064 updateDisplay procedureName?(blocks, head, tail, body, apple arguments?); // procedure call 1065 var currentDirRef name? = new AsRef<Direction>(currentDir)value or expression?;1066 var headRef name? = new AsRef<List<int>>(head)value or expression?;1067 var tailRef name? = new AsRef<List<int>>(tail)value or expression?;1068 updateSnake procedureName?(currentDirRef, tailRef, headRef, body arguments?); // procedure call 1069 head variableName? = headRef.value()value or expression?; // assignment 1070 tail variableName? = tailRef.value()value or expression?; // assignment 1071 currentDir variableName? = currentDirRef.value()value or expression?; // assignment 1072 gameOn variableName? = !hasHitEdge(head[0], head[1]) && !body.contains(head)value or expression?; // assignment 1073 +if (head.equals(apple)condition?) { 1074 setAppleToRandomPosition procedureName?(apple, body arguments?); // procedure call 1075 } else {1076 body.removeAt procedureName?(0 arguments?); // procedure call 1077 } // end if sleep_ms procedureName?(150 arguments?); // procedure call 1078 } // end while Console.WriteLine($"Game Over! Score: {body.length() - 1}"arguments?); // print statement 1079 } // end main
+Sub main() 1080 Dim blocks name? = createBlockGraphics(white)value or expression? ' variable definition 1081 Dim head name? = {20, 15}value or expression? ' variable definition 1082 Dim tail name? = head value or expression? ' variable definition 1083 Dim body name? = {head}value or expression? ' variable definition 1084 Dim currentDir name? = Direction.right value or expression? ' variable definition 1085 Dim gameOn name? = True value or expression? ' variable definition 1086 Dim apple name? = {0, 0}value or expression? ' variable definition 1087 setAppleToRandomPosition procedureName?(apple, body arguments?) ' procedure call 1088 +While gameOn condition? 1089 updateDisplay procedureName?(blocks, head, tail, body, apple arguments?) ' procedure call 1090 Dim currentDirRef name? = New AsRef(Of Direction)(currentDir)value or expression? ' variable definition 1091 Dim headRef name? = New AsRef(Of List(Of Integer))(head)value or expression? ' variable definition 1092 Dim tailRef name? = New AsRef(Of List(Of Integer))(tail)value or expression? ' variable definition 1093 updateSnake procedureName?(currentDirRef, tailRef, headRef, body arguments?) ' procedure call 1094 head variableName? = headRef.value()value or expression? ' assignment 1095 tail variableName? = tailRef.value()value or expression? ' assignment 1096 currentDir variableName? = currentDirRef.value()value or expression? ' assignment 1097 gameOn variableName? = Not hasHitEdge(head(0), head(1)) And Not body.contains(head)value or expression? ' assignment 1098 +If head.equals(apple)condition? Then 1099 setAppleToRandomPosition procedureName?(apple, body arguments?) ' procedure call 1100 Else 1101 body.removeAt procedureName?(0 arguments?) ' procedure call 1102 End If sleep_ms procedureName?(150 arguments?) ' procedure call 1103 End While Console.WriteLine($"Game Over! Score: {body.length() - 1}"arguments?) ' print statement 1104 End Sub
+static void main() { 1105 var blocks name? = createBlockGraphics(white)value or expression?;1106 var head name? = list(20, 15)value or expression?;1107 var tail name? = head value or expression?;1108 var body name? = list(head)value or expression?;1109 var currentDir name? = Direction.right value or expression?;1110 var gameOn name? = true value or expression?;1111 var apple name? = list(0, 0)value or expression?;1112 setAppleToRandomPosition procedureName?(apple, body arguments?); // procedure call 1113 +while (gameOn condition?) { 1114 updateDisplay procedureName?(blocks, head, tail, body, apple arguments?); // procedure call 1115 var currentDirRef name? = new AsRef<Direction>(currentDir)value or expression?;1116 var headRef name? = new AsRef<List<int>>(head)value or expression?;1117 var tailRef name? = new AsRef<List<int>>(tail)value or expression?;1118 updateSnake procedureName?(currentDirRef, tailRef, headRef, body arguments?); // procedure call 1119 head variableName? = headRef.value()value or expression?; // assignment 1120 tail variableName? = tailRef.value()value or expression?; // assignment 1121 currentDir variableName? = currentDirRef.value()value or expression?; // assignment 1122 gameOn variableName? = !hasHitEdge(head[0], head[1]) && !body.contains(head)value or expression?; // assignment 1123 +if (head.equals(apple)condition?) { 1124 setAppleToRandomPosition procedureName?(apple, body arguments?); // procedure call 1125 } else {1126 body.removeAt procedureName?(0 arguments?); // procedure call 1127 } // end if sleep_ms procedureName?(150 arguments?); // procedure call 1128 } // end while System.out.println(String.format("Game Over! Score: %", body.length() - 1)arguments?); // print statement 1129 } // end main

### What you need to know about a print statement

- The print statement writes a value to display.
- It automatically prints a new line after the value.
- The value can be any expression.
- You must provide a value; if you just want to print a blank line, just set the value to "".
- The recommended way to print multiple values is to use an interpolated string (see third example above)

### More advanced techniques

As an alternative to using the print statement you call one of these standard library procedures using procedure call instruction:

- printNoLine
- printWithTab

which offer more flexible options. These library methods work when running any of the supported languages within Elan but, unlike when using the normal the print statement, the library procedures do not correspond directly to print methods in the native libraries for those languages.

### See also

Interpolated string

printNoLine

printTab

## Variable definition

### Examples of a variable definition

From the Burrow demo, where variables named `xxxxx` and `yyyyy` represent the current coordinates for the burrowing 'animal':

variable x name? set to 20 value or expression?1130
x name? = 20 value or expression? # variable definition 1131
var x name? = 20 value or expression?;1132
Dim x name? = 20 value or expression? ' variable definition 1133
var x name? = 20 value or expression?;1134
variable y name? set to 15 value or expression?1135
y name? = 15 value or expression? # variable definition 1136
var y name? = 15 value or expression?;1137
Dim y name? = 15 value or expression? ' variable definition 1138
var y name? = 15 value or expression?;1139

and the values of these variables are used in multiple places within the program, for example here:

assign blocks[x][y]variableName? to red value or expression?1140
blocks[x][y]variableName? = red value or expression? # assignment 1141
blocks[x][y]variableName? = red value or expression?; // assignment 1142
blocks(x)(y)variableName? = red value or expression? ' assignment 1143
blocks[x][y]variableName? = red value or expression?; // assignment 1144

From the Life – procedural demo where a variable is initialised using an expression, in this case a function call:

variable grid name? set to createBlockGraphics(white)value or expression?1145
grid name? = createBlockGraphics(white)value or expression? # variable definition 1146
var grid name? = createBlockGraphics(white)value or expression?;1147
Dim grid name? = createBlockGraphics(white)value or expression? ' variable definition 1148
var grid name? = createBlockGraphics(white)value or expression?;1149

Example from the Ripple Sort demo where a variable being initialised using a literal list of integers:

variable li name? set to [7, 1, 0, 4, 8, 3, 6]value or expression?1150
li name? = [7, 1, 0, 4, 8, 3, 6]value or expression? # variable definition 1151
var li name? = new [] {7, 1, 0, 4, 8, 3, 6}value or expression?;1152
Dim li name? = {7, 1, 0, 4, 8, 3, 6}value or expression? ' variable definition 1153
var li name? = list(7, 1, 0, 4, 8, 3, 6)value or expression?;1154

### What you need to know about a variable definition

- A variable is a named value, were the value may be changed during the course of running the program.
- The variable definition instruction allows you to define a new variable.
- The instructions require a name (e.g. `xxxxx`) and an initial value.
- The initial value may be specified using a literal value (such as `2020202020`, or `"apple""apple""apple""apple""apple"`) or by an expression.
- The type of the initial value determines the type of the variable, so if/when the variable is later changed to a new value, that new value must be of that same type./li>
- Variables may only be defined within a method (the main routine, a procedure, or function).
- Elan does not permit 'global variables' to be defined – even though, outside Elan, that would be allowed by all the languages – because it is considered a bad practice.

## Assigment

### Examples of an assignment

From the Ripple sort demo, where the `hasChangedhasChangedhasChangedhasChangedhasChanged` variable, having been defined higher up, is assigned to `falseFalsefalseFalsefalse` at the start of the while loop, and then to `trueTruetrueTruetrue` if two values are swapped:

+procedure inPlaceRippleSort name?(li as List<of Int>parameter definitions?) 1155 variable hasChanged name? set to true value or expression?1156 variable lastComp name? set to li.length() - 2 value or expression?1157 +while hasChanged is true condition? 1158 assign hasChanged variableName? to false value or expression?1159 +for i item? in range(0, lastComp + 1)source? 1160 +if li[i] > li[i + 1]condition? then 1161 variable temp name? set to li[i]value or expression?1162 assign li[i]variableName? to li[i + 1]value or expression?1163 assign li[i + 1]variableName? to temp value or expression?1164 assign hasChanged variableName? to true value or expression?1165 end if end for assign lastComp variableName? to lastComp - 1 value or expression?1166 end while end procedure
+def inPlaceRippleSort name?(li: list[int]parameter definitions?) -> None: # procedure 1167 hasChanged name? = True value or expression? # variable definition 1168 lastComp name? = li.length() - 2 value or expression? # variable definition 1169 +while hasChanged == True condition?: 1170 hasChanged variableName? = False value or expression? # assignment 1171 +for i item? in range(0, lastComp + 1)source?: 1172 +if li[i] > li[i + 1]condition?: 1173 temp name? = li[i]value or expression? # variable definition 1174 li[i]variableName? = li[i + 1]value or expression? # assignment 1175 li[i + 1]variableName? = temp value or expression? # assignment 1176 hasChanged variableName? = True value or expression? # assignment 1177 # end if # end for lastComp variableName? = lastComp - 1 value or expression? # assignment 1178 # end while # end procedure
+static void inPlaceRippleSort name?(List<int> li parameter definitions?) { // procedure 1179 var hasChanged name? = true value or expression?;1180 var lastComp name? = li.length() - 2 value or expression?;1181 +while (hasChanged == true condition?) { 1182 hasChanged variableName? = false value or expression?; // assignment 1183 +foreach (var i item? in range(0, lastComp + 1)source?) { 1184 +if (li[i] > li[i + 1]condition?) { 1185 var temp name? = li[i]value or expression?;1186 li[i]variableName? = li[i + 1]value or expression?; // assignment 1187 li[i + 1]variableName? = temp value or expression?; // assignment 1188 hasChanged variableName? = true value or expression?; // assignment 1189 } // end if } // end foreach lastComp variableName? = lastComp - 1 value or expression?; // assignment 1190 } // end while } // end procedure
+Sub inPlaceRippleSort name?(li As List(Of Integer)parameter definitions?) ' procedure 1191 Dim hasChanged name? = True value or expression? ' variable definition 1192 Dim lastComp name? = li.length() - 2 value or expression? ' variable definition 1193 +While hasChanged = True condition? 1194 hasChanged variableName? = False value or expression? ' assignment 1195 +For Each i item? In range(0, lastComp + 1)source? 1196 +If li(i) > li(i + 1)condition? Then 1197 Dim temp name? = li(i)value or expression? ' variable definition 1198 li(i)variableName? = li(i + 1)value or expression? ' assignment 1199 li(i + 1)variableName? = temp value or expression? ' assignment 1200 hasChanged variableName? = True value or expression? ' assignment 1201 End If Next i lastComp variableName? = lastComp - 1 value or expression? ' assignment 1202 End While End Sub
+static void inPlaceRippleSort name?(List<int> li parameter definitions?) { // procedure 1203 var hasChanged name? = true value or expression?;1204 var lastComp name? = li.length() - 2 value or expression?;1205 +while (hasChanged == true condition?) { 1206 hasChanged variableName? = false value or expression?; // assignment 1207 +foreach (var i item? in range(0, lastComp + 1)source?) { 1208 +if (li[i] > li[i + 1]condition?) { 1209 var temp name? = li[i]value or expression?;1210 li[i]variableName? = li[i + 1]value or expression?; // assignment 1211 li[i + 1]variableName? = temp value or expression?; // assignment 1212 hasChanged variableName? = true value or expression?; // assignment 1213 } // end if } // end foreach lastComp variableName? = lastComp - 1 value or expression?; // assignment 1214 } // end while } // end procedure

From the Snake -procedural demo, where the variable `currentDefcurrentDefcurrentDefcurrentDefcurrentDef` is assigned to a new value by calling the function directionByKey, which is passed a keypress that has been read from the keyboard using the getKey system method:

Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.

### What you need to know about an assignment

- An assignment instruction assigns a new value to a variable that has been defined earlier within the method.
- The new value to be assigned may be defined as a literal value, or as the result of evaluating an expression.
- The new value must be of the same type as the one that the variable was defined with.

## Input statement

### Examples of an input statement

From the Binary Search demo, showing an input statement with a clear user-prompt:

input wanted name? set to inputString("What type of fruit do you want ('x' to exit)? "prompt message?)1215
wanted name? = input("What type of fruit do you want ('x' to exit)? "prompt message?) # input statement 1216
Console.WriteLine("What type of fruit do you want ('x' to exit)? "prompt message?);
var wanted name? = Console.ReadLine(); // input statement 1217
Console.WriteLine("What type of fruit do you want ('x' to exit)? "prompt message?)
Dim wanted name? = Console.ReadLine() ' input statement 1218
var wanted name? = Console.ReadLine("What type of fruit do you want ('x' to exit)? "prompt message?); // input statement 1219

### What you need to know about an input statement

- The input statement is the simplest way to read a string value typed in by the user (followed by Enter.
- You must specify a user-prompt string, though this may be an empty string – `""""""""""`.
- When working in Elan, the user entry will always be on the line below the displayed prompt.
- The entered value is put into a new variable – equivalent to if it was a variable definition.
- If you want to assign the input to an existing variable you can do this by adding an assignment on the next line.
- Also in a separate instruction, you can parse the string into a numeric type by applying the `asInt()asInt()asInt()asInt()asInt()` or `asFloat()asFloat()asFloat()asFloat()asFloat()` functions to the input variable, but note that these functions will throw an exception if the input string does not parse to the required numeric type.
- See below for more advanced options for handling specific forms of user input.

### More advanced techniques

#### System methods for keyboard input

As an alternative to using the input statement you may also use a range of system methods from the standard Elan library, which offer several advantages, including:

- Enforcing that a user input matches the requirement for an integer, or floating-point number, and then doing the conversion invisibly:
- Enforcing that either form of numeric input is within specified numeric bounds.
- Enforcing that a string input is within specified bounds for the number of characters.
- Enforcing that a string input matches one of a list of valid string responses.

In all these cases, if the user input does not match the specified rules, the user will be advised, and asked to input a value response.

See

Keyboard input for the full list of relevant system method.

## If statement

### Examples of an if statement

From the Life – procedural demo, where the `resultresultresultresultresult` is changed from black to white if a given random value (expected to be in the range 0 to 1) is greater than 0.5:

+function blackOrWhite name?(random as Float parameter definitions?) returns Int Type? 1220 variable result name? set to black value or expression?1221 +if random > 0.5 condition? then 1222 assign result variableName? to white value or expression?1223 end if return result value or expression?1224 end function
+def blackOrWhite name?(random: float parameter definitions?) -> int Type?: # function 1225 result name? = black value or expression? # variable definition 1226 +if random > 0.5 condition?: 1227 result variableName? = white value or expression? # assignment 1228 # end if return result value or expression?1229 # end function
+static int Type? blackOrWhite name?(double random parameter definitions?) { // function 1230 var result name? = black value or expression?;1231 +if (random > 0.5 condition?) { 1232 result variableName? = white value or expression?; // assignment 1233 } // end if return result value or expression?;1234 } // end function
+Function blackOrWhite name?(random As Double parameter definitions?) As Integer Type? 1235 Dim result name? = black value or expression? ' variable definition 1236 +If random > 0.5 condition? Then 1237 result variableName? = white value or expression? ' assignment 1238 End If Return result value or expression?1239 End Function
+static int Type? blackOrWhite name?(double random parameter definitions?) { // function 1240 var result name? = black value or expression?;1241 +if (random > 0.5 condition?) { 1242 result variableName? = white value or expression?; // assignment 1243 } // end if return result value or expression?;1244 } // end function

From the Bubbles demo where the if statement includes an else clause, so that one of two separate blocks of instructions is always executed depending on the value of a randomly-generated number.

+if random() < 0.05 condition? then 1245 # 5% chance bubble 'bursts' and starts again tiny at bottom comment? call b.setRadius procedureName?(0 arguments?)1246 call b.setCentreY procedureName?(75 arguments?)1247 else 1248 # bubble rises and grows slightly comment? call b.setCentreY procedureName?(b.centreY - 1 arguments?)1249 call b.setRadius procedureName?(b.radius + 0.2 arguments?)1250 end if
+if random() < 0.05 condition?: 1251 # 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?) # procedure call 1252 b.setCentreY procedureName?(75 arguments?) # procedure call 1253 else:1254 # bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?) # procedure call 1255 b.setRadius procedureName?(b.radius + 0.2 arguments?) # procedure call 1256 # end if
+if (random() < 0.05 condition?) { 1257 // 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?); // procedure call 1258 b.setCentreY procedureName?(75 arguments?); // procedure call 1259 } else {1260 // bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?); // procedure call 1261 b.setRadius procedureName?(b.radius + 0.2 arguments?); // procedure call 1262 } // end if
+If random() < 0.05 condition? Then 1263 ' 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?) ' procedure call 1264 b.setCentreY procedureName?(75 arguments?) ' procedure call 1265 Else 1266 ' bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?) ' procedure call 1267 b.setRadius procedureName?(b.radius + 0.2 arguments?) ' procedure call 1268 End If
+if (random() < 0.05 condition?) { 1269 // 5% chance bubble 'bursts' and starts again tiny at bottom comment? b.setRadius procedureName?(0 arguments?); // procedure call 1270 b.setCentreY procedureName?(75 arguments?); // procedure call 1271 } else {1272 // bubble rises and grows slightly comment? b.setCentreY procedureName?(b.centreY - 1 arguments?); // procedure call 1273 b.setRadius procedureName?(b.radius + 0.2 arguments?); // procedure call 1274 } // end if

From the Burrow demo, where the if includes multiple else if clause (shortened to 'elif' in some languages) clauses, such that depending on the value of the `directiondirectiondirectiondirectiondirection` variable, one of four different instructions is executed:

+if direction is 0 condition? then 1275 assign x variableName? to min([x + 1, 39])value or expression?1276 elif direction is 1 condition? then 1277 assign x variableName? to max([x - 1, 0])value or expression?1278 elif direction is 2 condition? then 1279 assign y variableName? to min([y + 1, 29])value or expression?1280 elif direction is 3 condition? then 1281 assign y variableName? to max([y - 1, 0])value or expression?1282 end if
+if direction == 0 condition?: 1283 x variableName? = min([x + 1, 39])value or expression? # assignment 1284 elif direction == 1 condition?: # else if 1285 x variableName? = max([x - 1, 0])value or expression? # assignment 1286 elif direction == 2 condition?: # else if 1287 y variableName? = min([y + 1, 29])value or expression? # assignment 1288 elif direction == 3 condition?: # else if 1289 y variableName? = max([y - 1, 0])value or expression? # assignment 1290 # end if
+if (direction == 0 condition?) { 1291 x variableName? = min(new [] {x + 1, 39})value or expression?; // assignment 1292 } else if (direction == 1 condition?) {1293 x variableName? = max(new [] {x - 1, 0})value or expression?; // assignment 1294 } else if (direction == 2 condition?) {1295 y variableName? = min(new [] {y + 1, 29})value or expression?; // assignment 1296 } else if (direction == 3 condition?) {1297 y variableName? = max(new [] {y - 1, 0})value or expression?; // assignment 1298 } // end if
+If direction = 0 condition? Then 1299 x variableName? = min({x + 1, 39})value or expression? ' assignment 1300 ElseIf direction = 1 condition? Then 1301 x variableName? = max({x - 1, 0})value or expression? ' assignment 1302 ElseIf direction = 2 condition? Then 1303 y variableName? = min({y + 1, 29})value or expression? ' assignment 1304 ElseIf direction = 3 condition? Then 1305 y variableName? = max({y - 1, 0})value or expression? ' assignment 1306 End If
+if (direction == 0 condition?) { 1307 x variableName? = min(list(x + 1, 39))value or expression?; // assignment 1308 } else if (direction == 1 condition?) {1309 x variableName? = max(list(x - 1, 0))value or expression?; // assignment 1310 } else if (direction == 2 condition?) {1311 y variableName? = min(list(y + 1, 29))value or expression?; // assignment 1312 } else if (direction == 3 condition?) {1313 y variableName? = max(list(y - 1, 0))value or expression?; // assignment 1314 } // end if

(Note: the last else if clause could have been written as an else clause, but writing it as an else if clause makes the intention clearer to a human reader).

### What you need to know about an if statement

- The if statement specifies which of several blocks of instructions is to be executed next.
- It requires a condition to be specified, which must evaluate to a Boolean value – `trueTruetrueTruetrue` or `falseFalsefalseFalsefalse`.
- That expression might take any of the following forms:
  - comparing two values using one of the Boolean operators e.g. `random() < 0.05random() < 0.05random() < 0.05random() < 0.05random() < 0.05` or `direction is 0direction == 0direction == 0direction = 0direction == 0`
  - a single existing variable that is of Boolean type
  - a function call, or any more complex expression, that evaluates to a Boolean value
- Within the body of an if statement you may add one or more else if clauses and/or a single else clause
- If you specify an else clause it must be the final clause within the if statement body

### See also

if_ function. This is an alternative way to implement conditions. Although that is introduced as part of functional programming', you may use it within the procedural paradigm.

## While loop

### Examples of a while loop

From the Ripple Sort demo, where the loop is executed until a pass right through the loop has left the `hasChangedhasChangedhasChangedhasChangedhasChanged` variable as `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.`

+while hasChanged is true condition? 1315 assign hasChanged variableName? to false value or expression?1316 +for i item? in range(0, lastComp + 1)source? 1317 +if li[i] > li[i + 1]condition? then 1318 variable temp name? set to li[i]value or expression?1319 assign li[i]variableName? to li[i + 1]value or expression?1320 assign li[i + 1]variableName? to temp value or expression?1321 assign hasChanged variableName? to true value or expression?1322 end if end for assign lastComp variableName? to lastComp - 1 value or expression?1323 end while
+while hasChanged == True condition?: 1324 hasChanged variableName? = False value or expression? # assignment 1325 +for i item? in range(0, lastComp + 1)source?: 1326 +if li[i] > li[i + 1]condition?: 1327 temp name? = li[i]value or expression? # variable definition 1328 li[i]variableName? = li[i + 1]value or expression? # assignment 1329 li[i + 1]variableName? = temp value or expression? # assignment 1330 hasChanged variableName? = True value or expression? # assignment 1331 # end if # end for lastComp variableName? = lastComp - 1 value or expression? # assignment 1332 # end while
+while (hasChanged == true condition?) { 1333 hasChanged variableName? = false value or expression?; // assignment 1334 +foreach (var i item? in range(0, lastComp + 1)source?) { 1335 +if (li[i] > li[i + 1]condition?) { 1336 var temp name? = li[i]value or expression?;1337 li[i]variableName? = li[i + 1]value or expression?; // assignment 1338 li[i + 1]variableName? = temp value or expression?; // assignment 1339 hasChanged variableName? = true value or expression?; // assignment 1340 } // end if } // end foreach lastComp variableName? = lastComp - 1 value or expression?; // assignment 1341 } // end while
+While hasChanged = True condition? 1342 hasChanged variableName? = False value or expression? ' assignment 1343 +For Each i item? In range(0, lastComp + 1)source? 1344 +If li(i) > li(i + 1)condition? Then 1345 Dim temp name? = li(i)value or expression? ' variable definition 1346 li(i)variableName? = li(i + 1)value or expression? ' assignment 1347 li(i + 1)variableName? = temp value or expression? ' assignment 1348 hasChanged variableName? = True value or expression? ' assignment 1349 End If Next i lastComp variableName? = lastComp - 1 value or expression? ' assignment 1350 End While
+while (hasChanged == true condition?) { 1351 hasChanged variableName? = false value or expression?; // assignment 1352 +foreach (var i item? in range(0, lastComp + 1)source?) { 1353 +if (li[i] > li[i + 1]condition?) { 1354 var temp name? = li[i]value or expression?;1355 li[i]variableName? = li[i + 1]value or expression?; // assignment 1356 li[i + 1]variableName? = temp value or expression?; // assignment 1357 hasChanged variableName? = true value or expression?; // assignment 1358 } // end if } // end foreach lastComp variableName? = lastComp - 1 value or expression?; // assignment 1359 } // end while

From the Bubbles demo, where the condition is 'hard-wired' to `trueTruetrueTruetrue`, which means that the loop will executive indefinitely (until you stop the program manually with the stop button):

+while true condition? 1360 call moveGrowBurst procedureName?(bubbles arguments?)1361 end while
+while True condition?: 1362 moveGrowBurst procedureName?(bubbles arguments?) # procedure call 1363 # end while
+while (true condition?) { 1364 moveGrowBurst procedureName?(bubbles arguments?); // procedure call 1365 } // end while
+While True condition? 1366 moveGrowBurst procedureName?(bubbles arguments?) ' procedure call 1367 End While
+while (true condition?) { 1368 moveGrowBurst procedureName?(bubbles arguments?); // procedure call 1369 } // end while

From the Tower of Hanoi demo, which uses a more complicated expression – to exit the loop only when the third stack has all the discs on it:

+while stacks[2].length() isnt nDiscs condition? 1370 +if (stacks[0].length() mod 2) is 0 condition? then 1371 call moveBetween procedureName?(stacks, 0, 1 arguments?)1372 call moveBetween procedureName?(stacks, 0, 2 arguments?)1373 call moveBetween procedureName?(stacks, 1, 2 arguments?)1374 else 1375 call moveBetween procedureName?(stacks, 0, 2 arguments?)1376 call moveBetween procedureName?(stacks, 0, 1 arguments?)1377 call moveBetween procedureName?(stacks, 1, 2 arguments?)1378 end if end while
+while stacks[2].length() != nDiscs condition?: 1379 +if (stacks[0].length() % 2) == 0 condition?: 1380 moveBetween procedureName?(stacks, 0, 1 arguments?) # procedure call 1381 moveBetween procedureName?(stacks, 0, 2 arguments?) # procedure call 1382 moveBetween procedureName?(stacks, 1, 2 arguments?) # procedure call 1383 else:1384 moveBetween procedureName?(stacks, 0, 2 arguments?) # procedure call 1385 moveBetween procedureName?(stacks, 0, 1 arguments?) # procedure call 1386 moveBetween procedureName?(stacks, 1, 2 arguments?) # procedure call 1387 # end if # end while
+while (stacks[2].length() != nDiscs condition?) { 1388 +if ((stacks[0].length() % 2) == 0 condition?) { 1389 moveBetween procedureName?(stacks, 0, 1 arguments?); // procedure call 1390 moveBetween procedureName?(stacks, 0, 2 arguments?); // procedure call 1391 moveBetween procedureName?(stacks, 1, 2 arguments?); // procedure call 1392 } else {1393 moveBetween procedureName?(stacks, 0, 2 arguments?); // procedure call 1394 moveBetween procedureName?(stacks, 0, 1 arguments?); // procedure call 1395 moveBetween procedureName?(stacks, 1, 2 arguments?); // procedure call 1396 } // end if } // end while
+While stacks(2).length() <> nDiscs condition? 1397 +If (stacks(0).length() Mod 2) = 0 condition? Then 1398 moveBetween procedureName?(stacks, 0, 1 arguments?) ' procedure call 1399 moveBetween procedureName?(stacks, 0, 2 arguments?) ' procedure call 1400 moveBetween procedureName?(stacks, 1, 2 arguments?) ' procedure call 1401 Else 1402 moveBetween procedureName?(stacks, 0, 2 arguments?) ' procedure call 1403 moveBetween procedureName?(stacks, 0, 1 arguments?) ' procedure call 1404 moveBetween procedureName?(stacks, 1, 2 arguments?) ' procedure call 1405 End If End While
+while (stacks[2].length() != nDiscs condition?) { 1406 +if ((stacks[0].length() % 2) == 0 condition?) { 1407 moveBetween procedureName?(stacks, 0, 1 arguments?); // procedure call 1408 moveBetween procedureName?(stacks, 0, 2 arguments?); // procedure call 1409 moveBetween procedureName?(stacks, 1, 2 arguments?); // procedure call 1410 } else {1411 moveBetween procedureName?(stacks, 0, 2 arguments?); // procedure call 1412 moveBetween procedureName?(stacks, 0, 1 arguments?); // procedure call 1413 moveBetween procedureName?(stacks, 1, 2 arguments?); // procedure call 1414 } // end if } // end while

### What you need to know about a while loop

- The while loop specifies that a block of instructions is to be repeated (or 'iterated') for as long as a specified condition is true.
- It should be used when you which to repeat something, but you don't know, in advance, how many times you need it to be repeated.
- As on an if statement, the condition in a while loop may be any expression that evaluates to a Boolean value.
- The condition is evaluated at the beginning of each pass through the loop.
- If the condition makes use of one or more variables (most do) then the variables must be defined before the start of the loop.
- It is possible that the condition could evaluate to false even on the first pass, in which case the instructions within the loop are not executed at all.
- Conversely, if the condition always evaluates to true, then the loop will executive indefintely; this can be deliberate, but may also be an accidental and unwanted behaviour caused by specifying the condition inaccurately.

### See also

- For loop

## For loop

### Examples of a for loop

From the Bubbles demo, where the loop is designed to execute exactly 20 times (the upped bound of the range function being exclusive) to create 20 bubbles of the same size, but of different (randomised) colours, and spread evenly across the bottom of the display:

+for i item? in range(1, 21)source? 1415 variable b name? set to (new CircleVG()).withCentreX(i*5 + 2).withCentreY(75).withRadius(0).withFillColour(transparent).withStrokeColour(randint(0, white))value or expression?1416 call bubbles.append procedureName?(b arguments?)1417 end for
+for i item? in range(1, 21)source?: 1418 b name? = (CircleVG()).withCentreX(i*5 + 2).withCentreY(75).withRadius(0).withFillColour(transparent).withStrokeColour(randint(0, white))value or expression? # variable definition 1419 bubbles.append procedureName?(b arguments?) # procedure call 1420 # end for
+foreach (var i item? in range(1, 21)source?) { 1421 var b name? = (new CircleVG()).withCentreX(i*5 + 2).withCentreY(75).withRadius(0).withFillColour(transparent).withStrokeColour(randint(0, white))value or expression?;1422 bubbles.append procedureName?(b arguments?); // procedure call 1423 } // end foreach
+For Each i item? In range(1, 21)source? 1424 Dim b name? = (New CircleVG()).withCentreX(i*5 + 2).withCentreY(75).withRadius(0).withFillColour(transparent).withStrokeColour(randint(0, white))value or expression? ' variable definition 1425 bubbles.append procedureName?(b arguments?) ' procedure call 1426 Next i
+foreach (var i item? in range(1, 21)source?) { 1427 var b name? = (new CircleVG()).withCentreX(i*5 + 2).withCentreY(75).withRadius(0).withFillColour(transparent).withStrokeColour(randint(0, white))value or expression?;1428 bubbles.append procedureName?(b arguments?); // procedure call 1429 } // end foreach

From the Turtle Dragon demo, where the number of times to execute the loop is calculated – based on the number of characters in the string variable named `turnsturnsturnsturnsturns`:

+procedure drawDragon name?(t as Turtle, order as Int, turns as String, side as Float, corner as Float parameter definitions?) 1430 variable p name? set to (200.0/order).floor()value or expression?1431 variable turnI name? set to 0 value or expression?1432 +for turn item? in turns source? 1433 assign turnI variableName? to (if_(turn.equals(left), 1, -1))value or expression?1434 call t.turn procedureName?(-45*turnI arguments?)1435 call t.move procedureName?(corner arguments?)1436 call t.turn procedureName?(-45*turnI arguments?)1437 call t.move procedureName?(side arguments?)1438 call sleep_ms procedureName?(p arguments?)1439 end for call t.penUp procedureName?(arguments?)1440 call t.hide procedureName?(arguments?)1441 end procedure
+def drawDragon name?(t: Turtle, order: int, turns: str, side: float, corner: float parameter definitions?) -> None: # procedure 1442 p name? = (200.0/order).floor()value or expression? # variable definition 1443 turnI name? = 0 value or expression? # variable definition 1444 +for turn item? in turns source?: 1445 turnI variableName? = (if_(turn.equals(left), 1, -1))value or expression? # assignment 1446 t.turn procedureName?(-45*turnI arguments?) # procedure call 1447 t.move procedureName?(corner arguments?) # procedure call 1448 t.turn procedureName?(-45*turnI arguments?) # procedure call 1449 t.move procedureName?(side arguments?) # procedure call 1450 sleep_ms procedureName?(p arguments?) # procedure call 1451 # end for t.penUp procedureName?(arguments?) # procedure call 1452 t.hide procedureName?(arguments?) # procedure call 1453 # end procedure
+static void drawDragon name?(Turtle t, int order, string turns, double side, double corner parameter definitions?) { // procedure 1454 var p name? = (200.0/order).floor()value or expression?;1455 var turnI name? = 0 value or expression?;1456 +foreach (var turn item? in turns source?) { 1457 turnI variableName? = (if_(turn.equals(left), 1, -1))value or expression?; // assignment 1458 t.turn procedureName?(-45*turnI arguments?); // procedure call 1459 t.move procedureName?(corner arguments?); // procedure call 1460 t.turn procedureName?(-45*turnI arguments?); // procedure call 1461 t.move procedureName?(side arguments?); // procedure call 1462 sleep_ms procedureName?(p arguments?); // procedure call 1463 } // end foreach t.penUp procedureName?(arguments?); // procedure call 1464 t.hide procedureName?(arguments?); // procedure call 1465 } // end procedure
+Sub drawDragon name?(t As Turtle, order As Integer, turns As String, side As Double, corner As Double parameter definitions?) ' procedure 1466 Dim p name? = (200.0/order).floor()value or expression? ' variable definition 1467 Dim turnI name? = 0 value or expression? ' variable definition 1468 +For Each turn item? In turns source? 1469 turnI variableName? = (if_(turn.equals(left), 1, -1))value or expression? ' assignment 1470 t.turn procedureName?(-45*turnI arguments?) ' procedure call 1471 t.move procedureName?(corner arguments?) ' procedure call 1472 t.turn procedureName?(-45*turnI arguments?) ' procedure call 1473 t.move procedureName?(side arguments?) ' procedure call 1474 sleep_ms procedureName?(p arguments?) ' procedure call 1475 Next turn t.penUp procedureName?(arguments?) ' procedure call 1476 t.hide procedureName?(arguments?) ' procedure call 1477 End Sub
+static void drawDragon name?(Turtle t, int order, String turns, double side, double corner parameter definitions?) { // procedure 1478 var p name? = (200.0/order).floor()value or expression?;1479 var turnI name? = 0 value or expression?;1480 +foreach (var turn item? in turns source?) { 1481 turnI variableName? = (if_(turn.equals(left), 1, -1))value or expression?; // assignment 1482 t.turn procedureName?(-45*turnI arguments?); // procedure call 1483 t.move procedureName?(corner arguments?); // procedure call 1484 t.turn procedureName?(-45*turnI arguments?); // procedure call 1485 t.move procedureName?(side arguments?); // procedure call 1486 sleep_ms procedureName?(p arguments?); // procedure call 1487 } // end foreach t.penUp procedureName?(arguments?); // procedure call 1488 t.hide procedureName?(arguments?); // procedure call 1489 } // end procedure

From the Life – procedural demo, a 'nested' for loop (one inside another) to apply the two inner instructions to each cell in the 40 x 30 grid:

+for x item? in range(0, 40)source? 1490 +for y item? in range(0, 30)source? 1491 variable colour name? set to nextCellValue(grid, x, y)value or expression?1492 assign nextGen[x][y]variableName? to colour value or expression?1493 end for end for
+for x item? in range(0, 40)source?: 1494 +for y item? in range(0, 30)source?: 1495 colour name? = nextCellValue(grid, x, y)value or expression? # variable definition 1496 nextGen[x][y]variableName? = colour value or expression? # assignment 1497 # end for # end for
+foreach (var x item? in range(0, 40)source?) { 1498 +foreach (var y item? in range(0, 30)source?) { 1499 var colour name? = nextCellValue(grid, x, y)value or expression?;1500 nextGen[x][y]variableName? = colour value or expression?; // assignment 1501 } // end foreach } // end foreach
+For Each x item? In range(0, 40)source? 1502 +For Each y item? In range(0, 30)source? 1503 Dim colour name? = nextCellValue(grid, x, y)value or expression? ' variable definition 1504 nextGen(x)(y)variableName? = colour value or expression? ' assignment 1505 Next y Next x
+foreach (var x item? in range(0, 40)source?) { 1506 +foreach (var y item? in range(0, 30)source?) { 1507 var colour name? = nextCellValue(grid, x, y)value or expression?;1508 nextGen[x][y]variableName? = colour value or expression?; // assignment 1509 } // end foreach } // end foreach

### What you need to know about a for loop

- The Elan concept of a for loop is equivalent to a 'for each' loop in C# and VB.
- It should be used when you know (or can work out), in advance, how many times you need it to be repeated.
- The for loop specifies that a block of instructions that is repeated, once for each value in a sequence.
- The value is held in a variable – which is defined in the first editable field when you create a new for instruction.
- The second field in the instruction specifies the sequence of values that will be assigned to the variable, successively.
- The sequence of values may be specified:
  - as a literal list (of any kind), or a variable of type list
  - as a string value, in which case each single character that makes up the string is assigned to the variable in succession
  - as any expression that generates a List
- When a sequence of consecutive integer values is needed the most common way to do this is by calling one of these two functions:
  - range requires two arguments: the lower and upper bound; the upper bound is 'exclusive' so that `range(1, 11)range(1, 11)range(1, 11)range(1, 11)range(1, 11)` creates the sequence 1,2,3,4,5,6,7,8,9,10
  - rangeInSteps requires three arguments: lower bound, upper bound (exclusive), and the 'step' or increment value, which can be negative provided that the upper bound is then less than the lower bound.
- The variable is updated each pass around the loop; you should not attempt to modify the variable defined in the loop's signature from within the loop.

### See also

- While loop

## Procedure call

### Examples of a procedure call

From the Burrow demo: a call to the library procedure named displayBlocks, passing in the data structure held in variable `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.`

call displayBlocks procedureName?(blocks arguments?)1510
displayBlocks procedureName?(blocks arguments?) # procedure call 1511
displayBlocks procedureName?(blocks arguments?); // procedure call 1512
displayBlocks procedureName?(blocks arguments?) ' procedure call 1513
displayBlocks procedureName?(blocks arguments?); // procedure call 1514

From the Bubbles demo, a call from within the main routine to the procedure named moveGrowBurst procedure:

call moveGrowBurst procedureName?(bubbles arguments?)1515
moveGrowBurst procedureName?(bubbles arguments?) # procedure call 1516
moveGrowBurst procedureName?(bubbles arguments?); // procedure call 1517
moveGrowBurst procedureName?(bubbles arguments?) ' procedure call 1518
moveGrowBurst procedureName?(bubbles arguments?); // procedure call 1519
which is defined immediately below the main routine at the same (global) level.

From the Snake – procedural demo, a procedure that contains a sequence of four calls to other procedures:

+procedure updateSnake name?(currentDirRef as AsRef<of Direction>, tailRef as AsRef<of List<of Int>>, headRef as AsRef<of List<of Int>>, body as List<of List<of Int>>parameter definitions?) 1520 variable head name? set to headRef.value()value or expression?1521 variable tail name? set to tailRef.value()value or expression?1522 variable currentDir name? set to currentDirRef.value()value or expression?1523 assign currentDir variableName? to directionByKey(currentDir, getKey())value or expression?1524 call tailRef.set procedureName?(body[0]arguments?)1525 call body.append procedureName?(head arguments?)1526 call headRef.set procedureName?(getAdjacentSquare(head, currentDir)arguments?)1527 call currentDirRef.set procedureName?(currentDir arguments?)1528 end procedure
+def updateSnake name?(currentDirRef: AsRef[Direction], tailRef: AsRef[list[int]], headRef: AsRef[list[int]], body: list[list[int]]parameter definitions?) -> None: # procedure 1529 head name? = headRef.value()value or expression? # variable definition 1530 tail name? = tailRef.value()value or expression? # variable definition 1531 currentDir name? = currentDirRef.value()value or expression? # variable definition 1532 currentDir variableName? = directionByKey(currentDir, getKey())value or expression? # assignment 1533 tailRef.set procedureName?(body[0]arguments?) # procedure call 1534 body.append procedureName?(head arguments?) # procedure call 1535 headRef.set procedureName?(getAdjacentSquare(head, currentDir)arguments?) # procedure call 1536 currentDirRef.set procedureName?(currentDir arguments?) # procedure call 1537 # end procedure
+static void updateSnake name?(AsRef<Direction> currentDirRef, AsRef<List<int>> tailRef, AsRef<List<int>> headRef, List<List<int>> body parameter definitions?) { // procedure 1538 var head name? = headRef.value()value or expression?;1539 var tail name? = tailRef.value()value or expression?;1540 var currentDir name? = currentDirRef.value()value or expression?;1541 currentDir variableName? = directionByKey(currentDir, getKey())value or expression?; // assignment 1542 tailRef.set procedureName?(body[0]arguments?); // procedure call 1543 body.append procedureName?(head arguments?); // procedure call 1544 headRef.set procedureName?(getAdjacentSquare(head, currentDir)arguments?); // procedure call 1545 currentDirRef.set procedureName?(currentDir arguments?); // procedure call 1546 } // end procedure
+Sub updateSnake name?(currentDirRef As AsRef(Of Direction), tailRef As AsRef(Of List(Of Integer)), headRef As AsRef(Of List(Of Integer)), body As List(Of List(Of Integer))parameter definitions?) ' procedure 1547 Dim head name? = headRef.value()value or expression? ' variable definition 1548 Dim tail name? = tailRef.value()value or expression? ' variable definition 1549 Dim currentDir name? = currentDirRef.value()value or expression? ' variable definition 1550 currentDir variableName? = directionByKey(currentDir, getKey())value or expression? ' assignment 1551 tailRef.set procedureName?(body(0)arguments?) ' procedure call 1552 body.append procedureName?(head arguments?) ' procedure call 1553 headRef.set procedureName?(getAdjacentSquare(head, currentDir)arguments?) ' procedure call 1554 currentDirRef.set procedureName?(currentDir arguments?) ' procedure call 1555 End Sub
+static void updateSnake name?(AsRef<Direction> currentDirRef, AsRef<List<int>> tailRef, AsRef<List<int>> headRef, List<List<int>> body parameter definitions?) { // procedure 1556 var head name? = headRef.value()value or expression?;1557 var tail name? = tailRef.value()value or expression?;1558 var currentDir name? = currentDirRef.value()value or expression?;1559 currentDir variableName? = directionByKey(currentDir, getKey())value or expression?; // assignment 1560 tailRef.set procedureName?(body[0]arguments?); // procedure call 1561 body.append procedureName?(head arguments?); // procedure call 1562 headRef.set procedureName?(getAdjacentSquare(head, currentDir)arguments?); // procedure call 1563 currentDirRef.set procedureName?(currentDir arguments?); // procedure call 1564 } // end procedure

Note that in each of those calls, the name of the procedure being called is preceded by an variable name and dot. This is known as 'dot syntax' and is used when the procedure is defined as a procedure method on a specified type. For example, in the call to `body.append(head)body.append(head)body.append(head)body.append(head)body.append(head)`, append is a procedure method on the type `ListlistListListList`, which is the type of the `bodybodybodybodybody` variable.

### What you need to know about a procedure call

- The procedure call instruction is used when you want to run a procedure .
- 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.
- Procedures may have side effects, for example input/output or changing a data value in an object. For this reason, procedures cannot be called from functions, which are not allowed to have side effects. To enforce this, procedure calls are not allowed in functions.
- There is a limit to the complexity allowed in a procedure call 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 .

### More advanced techniques

TODO: write afresh descriptions of mutating a (mutable) parameter, and, separately passing by Ref.

## Try statement

### Examples of a try statement

### What you need to know about a try statement

- The try statement is a mechanism to execute code that might result in an 'exception' (called an 'error' in some languages), and to catch that exception without the program being automatically halted.
- The try statement instruction is sometimes referred to as a `try-catch` – because it makes no sense to have a try statement without a catch clause.
- When you add a try statement instruction in Elan, the 'catch' clause is automatically included in the instruction frame (template).
- 'except' is Python's word for 'catch'
- When you add a new try statement the instructions that you want to try to execute are specified immediately underneath the first line.
- Underneath the catch clause you may instructions to handle the exception, for example by advising the user to try again.
- The catch clause must specify the type of the exception to be caught. When working in Elan, only two types are permitted:
  - `ElanRuntimeErrorElanRuntimeErrorElanRuntimeErrorElanRuntimeErrorElanRuntimeError` which covers all errors thrown by the Elan system, including, for example 'Out of range index ...'
  - `CustomErrorCustomErrorCustomErrorCustomErrorCustomError` an exception explicitly thrown by code by a throw statement in your own code (see below).
- Currently Elan currently permits only one catch clause to be associated with each try statement

You can enclose code in a try statement 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 statement 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 statement.

## Throw statement

### Examples of a throw statement

The following function to calculate factorials deliberately 'throws' an exception (error) if it is given a negative value for the argument:

+function factorial name?(n as Int parameter definitions?) returns Int Type? 1635 variable result name? set to 1 value or expression?1636 +if n > 1 condition? then 1637 assign result variableName? to n*factorial(n - 1)value or expression?1638 elif n < 0 condition? then 1639 throw CustomError exception type? "Factorial cannot be called with a negative argument"message?1640 end if return result value or expression?1641 end function
+def factorial name?(n: int parameter definitions?) -> int Type?: # function 1642 result name? = 1 value or expression? # variable definition 1643 +if n > 1 condition?: 1644 result variableName? = n*factorial(n - 1)value or expression? # assignment 1645 elif n < 0 condition?: # else if 1646 raise CustomError exception type?("Factorial cannot be called with a negative argument"message?)1647 # end if return result value or expression?1648 # end function
+static int Type? factorial name?(int n parameter definitions?) { // function 1649 var result name? = 1 value or expression?;1650 +if (n > 1 condition?) { 1651 result variableName? = n*factorial(n - 1)value or expression?; // assignment 1652 } else if (n < 0 condition?) {1653 throw new CustomError exception type?("Factorial cannot be called with a negative argument"message?);1654 } // end if return result value or expression?;1655 } // end function
+Function factorial name?(n As Integer parameter definitions?) As Integer Type? 1656 Dim result name? = 1 value or expression? ' variable definition 1657 +If n > 1 condition? Then 1658 result variableName? = n*factorial(n - 1)value or expression? ' assignment 1659 ElseIf n < 0 condition? Then 1660 Throw New CustomError exception type?("Factorial cannot be called with a negative argument"message?)1661 End If Return result value or expression?1662 End Function
+static int Type? factorial name?(int n parameter definitions?) { // function 1663 var result name? = 1 value or expression?;1664 +if (n > 1 condition?) { 1665 result variableName? = n*factorial(n - 1)value or expression?; // assignment 1666 } else if (n < 0 condition?) {1667 throw new CustomError exception type?("Factorial cannot be called with a negative argument"message?);1668 } // end if return result value or expression?;1669 } // end function

### What you need to know about a throw statement

- The throw statement will cause an 'exception' to be 'thrown' (or 'raised' in some languages).
- Unless the throw statement is directly or indirectly within a Try statement (see above), program execution will be halted and the message defined in the throw statement printed on the display.
- Because of this drastic effect it is recommended not to throw exceptions only in rare circumstances.

## Assert statement

### Examples of an assert statement

From the Tower of Hanoi

demo, showing an assert for an error case:
+test test_colour test_name? 1695 # Normal cases comment? assert colour(5)actual (computed) value? is green expected value? not run 1696 # Edge cases comment? assert colour(1)actual (computed) value? is red expected value? not run 1697 assert colour(10)actual (computed) value? is 0xFF99CC expected value? not run 1698 # Error cases comment? assert colour(11)actual (computed) value? is "Out of range index: 10 size: 10"expected value? not run 1699 end test
+class Test_colour(unittest.TestCase):
def test_colour test_name?(self) -> None: 1700 # Normal cases comment? self.assertEqual(colour(5)actual (computed) value?, green expected value?) not run 1701 # Edge cases comment? self.assertEqual(colour(1)actual (computed) value?, red expected value?) not run 1702 self.assertEqual(colour(10)actual (computed) value?, 0xFF99CC expected value?) not run 1703 # Error cases comment? self.assertEqual(colour(11)actual (computed) value?, "Out of range index: 10 size: 10"expected value?) not run 1704 # end test
+[TestClass] class Test_colour
[TestMethod] static void test_colour test_name?() { 1705 // Normal cases comment? Assert.AreEqual(green expected value?, colour(5)actual (computed) value?); not run 1706 // Edge cases comment? Assert.AreEqual(red expected value?, colour(1)actual (computed) value?); not run 1707 Assert.AreEqual(0xFF99CC expected value?, colour(10)actual (computed) value?); not run 1708 // Error cases comment? Assert.AreEqual("Out of range index: 10 size: 10"expected value?, colour(11)actual (computed) value?); not run 1709 }} // end test
+<TestClass Class Test_colour
<TestMethod> Sub test_colour test_name?() 1710 ' Normal cases comment? Assert.AreEqual(green expected value?, colour(5)actual (computed) value?) not run 1711 ' Edge cases comment? Assert.AreEqual(red expected value?, colour(1)actual (computed) value?) not run 1712 Assert.AreEqual(&HFF99CC expected value?, colour(10)actual (computed) value?) not run 1713 ' Error cases comment? Assert.AreEqual("Out of range index: 10 size: 10"expected value?, colour(11)actual (computed) value?) not run 1714 End Sub
End Class
+class Test_colour {
@Test static void test_colour test_name?() { 1715 // Normal cases comment? assertEquals(green expected value?, colour(5)actual (computed) value?); not run 1716 // Edge cases comment? assertEquals(red expected value?, colour(1)actual (computed) value?); not run 1717 assertEquals(0xFF99CC expected value?, colour(10)actual (computed) value?); not run 1718 // Error cases comment? assertEquals("Out of range index: 10 size: 10"expected value?, colour(11)actual (computed) value?); not run 1719 }} // end test

### What you need to know about an assert statement

- An assert instruction is used to test an individual case within a test, or sometimes to test individual result values in a single case that returns a data structure.
- The assert defines two fields that the user must specify:
  - The actual value as returned by a call to the function being tested.
  - The expected value, which will typically be a literal value of the same type as the actual.
  - When the tests are run (automatically whenever the code compiles) the result – pass or fail – will be shown alongside each assert.
  - A fail indicates that the expected and actual values do not match.
  - The expected value should be of the same type as the actual; if they are not that will be reported as a test failure, without showing the actual values.
  - You can, however, test for an exception having been thrown, by setting the expected value to a the expected error message (as a string).
  - Unlike on many systems, Elan does not stop at the first failure within each test – it will attempt to evaluate all the asserts.
  - The required order of the actual and expected fields varies between the supported languages; Elan handles this automatically when translating between languages.

## Comment

Comments can be inserted adjacent to statement instructions just like those at global level: see Comment 

# 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  | `trueTruetrueTruetrue`
String  | `"Hello""Hello""Hello""Hello""Hello"`
Tuple  | `(3, "banana")(3, "banana")(3, "banana")(3, "banana")(3, "banana")`
List  | `["lemon", "lime", "orange"]["lemon", "lime", "orange"]new [] {"lemon", "lime", "orange"}{"lemon", "lime", "orange"}list("lemon", "lime", "orange")`

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 1720 variable a name? set to "Hello world!"value or expression?1721 print(a[4]arguments?)1722 print(a.subString(4, a.length())arguments?)1723 print(a.subString(0, 7)arguments?)1724 end main +def main() -> None: 1725 a name? = "Hello world!"value or expression? # variable definition 1726 print(a[4]arguments?)1727 print(a.subString(4, a.length())arguments?)1728 print(a.subString(0, 7)arguments?)1729 # end main +static void main() { 1730 var a name? = "Hello world!"value or expression?;1731 Console.WriteLine(a[4]arguments?); // print statement 1732 Console.WriteLine(a.subString(4, a.length())arguments?); // print statement 1733 Console.WriteLine(a.subString(0, 7)arguments?); // print statement 1734 } // end main +Sub main() 1735 Dim a name? = "Hello world!"value or expression? ' variable definition 1736 Console.WriteLine(a(4)arguments?) ' print statement 1737 Console.WriteLine(a.subString(4, a.length())arguments?) ' print statement 1738 Console.WriteLine(a.subString(0, 7)arguments?) ' print statement 1739 End Sub +static void main() { 1740 var a name? = "Hello world!"value or expression?;1741 System.out.println(a[4]arguments?); // print statement 1742 System.out.println(a.subString(4, a.length())arguments?); // print statement 1743 System.out.println(a.subString(0, 7)arguments?); // print statement 1744 } // end main | ⟶ ⟶ ⟶ | o o world! Hello w< (since the upper bound of a range is exclusive)

And on a list:

+main 1745 variable li name? set to new List<of Int>()value or expression?1746 assign li variableName? to [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]value or expression?1747 print(li[4]arguments?)1748 print(li.subList(4, li.length())arguments?)1749 print(li.subList(0, 7)arguments?)1750 end main +def main() -> None: 1751 li name? = list[int]()value or expression? # variable definition 1752 li variableName? = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]value or expression? # assignment 1753 print(li[4]arguments?)1754 print(li.subList(4, li.length())arguments?)1755 print(li.subList(0, 7)arguments?)1756 # end main +static void main() { 1757 var li name? = new List<int>()value or expression?;1758 li variableName? = new [] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}value or expression?; // assignment 1759 Console.WriteLine(li[4]arguments?); // print statement 1760 Console.WriteLine(li.subList(4, li.length())arguments?); // print statement 1761 Console.WriteLine(li.subList(0, 7)arguments?); // print statement 1762 } // end main +Sub main() 1763 Dim li name? = New List(Of Integer)()value or expression? ' variable definition 1764 li variableName? = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}value or expression? ' assignment 1765 Console.WriteLine(li(4)arguments?) ' print statement 1766 Console.WriteLine(li.subList(4, li.length())arguments?) ' print statement 1767 Console.WriteLine(li.subList(0, 7)arguments?) ' print statement 1768 End Sub +static void main() { 1769 var li name? = new List<int>()value or expression?;1770 li variableName? = list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)value or expression?; // assignment 1771 System.out.println(li[4]arguments?); // print statement 1772 System.out.println(li.subList(4, li.length())arguments?); // print statement 1773 System.out.println(li.subList(0, 7)arguments?); // print statement 1774 } // end 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 the library function pow :

`print(pow(4, 4)arguments?)5print(pow(4, 4)arguments?)6Console.WriteLine(pow(4, 4)arguments?); // print statement7Console.WriteLine(pow(4, 4)arguments?) ' print statement8System.out.println(pow(4, 4)arguments?); // print statement9`
`variable cname? set to sqrt(pow(a, 2) + pow(b, 2))value or expression?10cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression? # variable definition11var cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression?;12Dim cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression? ' variable definition13var cname? = sqrt(pow(a, 2) + pow(b, 2))value or expression?;14`

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 `BooleanboolboolBooleanboolean` arguments and return a `BooleanboolboolBooleanboolean` 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? 1775 return a and not b or b and not a value or expression?1776 end function
+def exOr name?(a: bool, b: bool parameter definitions?) -> bool Type?: # function 1777 return a and not b or b and not a value or expression?1778 # end function
+static bool Type? exOr name?(bool a, bool b parameter definitions?) { // function 1779 return a && !b || b && !a value or expression?;1780 } // end function
+Function exOr name?(a As Boolean, b As Boolean parameter definitions?) As Boolean Type? 1781 Return a And Not b Or b And Not a value or expression?1782 End Function
+static boolean Type? exOr name?(boolean a, boolean b parameter definitions?) { // function 1783 return a && !b || b && !a value or expression?;1784 } // end function

### String operator

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

### Equality testing

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

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

- isnt returns the opposite of is.
- `(a is b)(a == b)(a == b)(a = b)(a == b)` returns `trueTruetrueTruetrue`, if `aaaaa` 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 `trueTruetrueTruetrue` (and isnt will return `falseFalsefalseFalsefalse`) 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 1785 new code end if
  +if listA.equals(listB)condition?: 1786 new code # end if
  +if (listA.equals(listB)condition?) { 1787 new code } // end if
  +If listA.equals(listB)condition? Then 1788 new code End If
  +if (listA.equals(listB)condition?) { 1789 new code } // end if
- `assign differsvariableName? to set1.notEqualTo(set2)value or expression?15differsvariableName? = set1.notEqualTo(set2)value or expression? # assignment16differsvariableName? = set1.notEqualTo(set2)value or expression?; // assignment17differsvariableName? = set1.notEqualTo(set2)value or expression? ' assignment18differsvariableName? = set1.notEqualTo(set2)value or expression?; // assignment19`

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:

`assign xvariableName? to (a > b) and (b < c)value or expression?20xvariableName? = (a > b) and (b < c)value or expression? # assignment21xvariableName? = (a > b) && (b < c)value or expression?; // assignment22xvariableName? = (a > b) And (b < c)value or expression? ' assignment23xvariableName? = (a > b) && (b < c)value or expression?; // assignment24`
`assign xvariableName? to (a + b) > (c - d)value or expression?25xvariableName? = (a + b) > (c - d)value or expression? # assignment26xvariableName? = (a + b) > (c - d)value or expression?; // assignment27xvariableName? = (a + b) > (c - d)value or expression? ' assignment28xvariableName? = (a + b) > (c - d)value or expression?; // assignment29`

## Function reference

An expression may simply be a reference to a function, or it may include several function references within it. Examples:
+main 1790 print(sin(radians(30))arguments?)1791 variable x name? set to pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression?1792 variable name name? set to input("Your name")value or expression?1793 print(name.upperCase()arguments?)1794 end main
+def main() -> None: 1795 print(sin(radians(30))arguments?)1796 x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression? # variable definition 1797 name name? = input("Your name")value or expression? # variable definition 1798 print(name.upperCase()arguments?)1799 # end main
+static void main() { 1800 Console.WriteLine(sin(radians(30))arguments?); // print statement 1801 var x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression?;1802 var name name? = input("Your name")value or expression?;1803 Console.WriteLine(name.upperCase()arguments?); // print statement 1804 } // end main
+Sub main() 1805 Console.WriteLine(sin(radians(30))arguments?) ' print statement 1806 Dim x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression? ' variable definition 1807 Dim name name? = input("Your name")value or expression? ' variable definition 1808 Console.WriteLine(name.upperCase()arguments?) ' print statement 1809 End Sub
+static void main() { 1810 System.out.println(sin(radians(30))arguments?); // print statement 1811 var x name? = pow(sin(radians(30)), 2) + pow(cos(radians(30)), 2)value or expression?;1812 var name name? = input("Your name")value or expression?;1813 System.out.println(name.upperCase()arguments?); // print statement 1814 } // end 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.

A lambda may be thought of as a one-line function that is defined where it is used. Like a function it defines one or more parameters, and an expression that depends on the parameter value(s). Thus, the lambda:

Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.

is equivalent to defining a function:

+function someName name?(x as Float parameter definitions?) returns Float Type? 1815 return x.round(8)value or expression?1816 end function
+def someName name?(x: float parameter definitions?) -> float Type?: # function 1817 return x.round(8)value or expression?1818 # end function
+static double Type? someName name?(double x parameter definitions?) { // function 1819 return x.round(8)value or expression?;1820 } // end function
+Function someName name?(x As Double parameter definitions?) As Double Type? 1821 Return x.round(8)value or expression?1822 End Function
+static double Type? someName name?(double x parameter definitions?) { // function 1823 return x.round(8)value or expression?;1824 } // end function

The lambda above is usually verbalised as 'lambda x returns x.round(8)`

The advantages of using a lambda (where one is allowed) instead of defining a function are:

- it is more succinct,
- it is defined exactly where it is used, so you don't need to navigate to the function to see what it does,

Here are some more examples of the syntax for a lambda:

Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.

Note that currently it is necessary to specify the type of each parameter in a lambda explicitly. We hope to remove this requirement in a future version – to make the syntax for a lambda cleaner.

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

## if expression

An 'if expression' has some similarity with an if statement, but with important differences:

- An 'if expression' is written within a single line.
- An 'if expression' always returns a value
- An 'if expression' may be used where an expression is expected in code, for example to define the value to be assigned to a variable.
- An 'if expression' may form part of a more complex expression.

All modern languages, including Python, VB, C#, and Java, support this concept, though sometimes by another name such as 'conditional expression', or even 'ternary operator' (because it has three terms). The syntax varies significantly between those languages. When coding with Elan in any of the supported languages, this functionality is provided by a 'pseudo function' named if_, The reason for the underscore is to distinguish the name from the if keyword used by all the languages as the start of an if statement. (This is consistent the standard advice that if you define your own identifier that classes with a reserved word, the simplest fix is to add an underscore on the end.)

The if_ function returns one of two values dependent upon the evaulation of a Boolean value:

Its syntax is shown here:

`variable isBiggername? set to if_(a >= b, true, false)value or expression?30isBiggername? = if_(a >= b, True, False)value or expression? # variable definition31var isBiggername? = if_(a >= b, true, false)value or expression?;32Dim isBiggername? = if_(a >= b, True, False)value or expression? ' variable definition33var isBiggername? = if_(a >= b, true, false)value or expression?;34`

Similarly, but returning an evaluated expression:

`variable dname? set to if_(c < 580, c - 40, c + 60)value or expression?35dname? = if_(c < 580, c - 40, c + 60)value or expression? # variable definition36var dname? = if_(c < 580, c - 40, c + 60)value or expression?;37Dim dname? = if_(c < 580, c - 40, c + 60)value or expression? ' variable definition38var dname? = if_(c < 580, c - 40, c + 60)value or expression?;39`

in which variable `ddddd` 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_ function may be used within an if_ function but may be hard to read and understand.

Why do we refer to if_ as a 'pseudo function'. At first glance it looks to operate like any function: it requires three arguments and returns a result that depends on them. But it does one thing very differently: if either or both of the second and third arguments are themselves defined by expressions, they are evaluated lazily – only the one that is is needed (depending on the evaluation of the condition argument) will be evaluated. It turns out that this is very important – without it can be very easy to end up with lots of 'Stack overflow errors'. So though if_ looks like any other library function, it is actually special syntax. And that is why you don't see if_ offered in the drop-down list of library function names.

### Examples using if_ function:

● Choice in a return instruction:

+function foo name?(parameter definitions parameter definitions?) returns Int Type? 1825 return if_(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?1826 end function
+def foo name?(parameter definitions parameter definitions?) -> int Type?: # function 1827 return if_(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?1828 # end function
+static int Type? foo name?(parameter definitions parameter definitions?) { // function 1829 return if_(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?;1830 } // end function
+Function foo name?(parameter definitions parameter definitions?) As Integer Type? 1831 Return if_(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?1832 End Function
+static int Type? foo name?(parameter definitions parameter definitions?) { // function 1833 return if_(isGreen(attempt, target, n), setChar(attempt, n, "*"), attempt)value or expression?;1834 } // end function

● Using an if_ function in a procedure call print:

+main 1835 variable p name? set to unicode(0x03c0)value or expression?1836 call testPi procedureName?(p, 3 arguments?)1837 call testPi procedureName?(p, 4 arguments?)1838 end main +def main() -> None: 1839 p name? = unicode(0x03c0)value or expression? # variable definition 1840 testPi procedureName?(p, 3 arguments?) # procedure call 1841 testPi procedureName?(p, 4 arguments?) # procedure call 1842 # end main +static void main() { 1843 var p name? = unicode(0x03c0)value or expression?;1844 testPi procedureName?(p, 3 arguments?); // procedure call 1845 testPi procedureName?(p, 4 arguments?); // procedure call 1846 } // end main +Sub main() 1847 Dim p name? = unicode(&H03c0)value or expression? ' variable definition 1848 testPi procedureName?(p, 3 arguments?) ' procedure call 1849 testPi procedureName?(p, 4 arguments?) ' procedure call 1850 End Sub +static void main() { 1851 var p name? = unicode(0x03c0)value or expression?;1852 testPi procedureName?(p, 3 arguments?); // procedure call 1853 testPi procedureName?(p, 4 arguments?); // procedure call 1854 } // end main | ⟶ ⟶ | π > 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 – procedural:

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

# Miscellaneous

## 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 `StringstrstringStringString` `sssss` using a library method:
  `variable nname? set to s.length()value or expression?45nname? = s.length()value or expression? # variable definition46var nname? = s.length()value or expression?;47Dim nname? = s.length()value or expression? ' variable definition48var nname? = s.length()value or expression?;49`
- To apply a procedure to a named value, e.g. to initialise `ListlistListListList` `lilililili` using a library procedure:
  `call li.initialiseprocedureName?(10, 0arguments?)50li.initialiseprocedureName?(10, 0arguments?) # procedure call51li.initialiseprocedureName?(10, 0arguments?); // procedure call52li.initialiseprocedureName?(10, 0arguments?) ' procedure call53li.initialiseprocedureName?(10, 0arguments?); // procedure call54`
- To refer to the property (`bodybodybodybodybody`) of an instance (`gamegamegamegamegame`) of a class and, in this example to get the length of the property's current string value, using library methods:
  `variable bodyGLname? set to game.body.toString().length()value or expression?55bodyGLname? = game.body.toString().length()value or expression? # variable definition56var bodyGLname? = game.body.toString().length()value or expression?;57Dim bodyGLname? = game.body.toString().length()value or expression? ' variable definition58var bodyGLname? = game.body.toString().length()value or expression?;59`
- 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 point name? set to (3, 7)value or expression?1855
  point name? = (3, 7)value or expression? # variable definition 1856
  var point name? = (3, 7)value or expression?;1857
  Dim point name? = (3, 7)value or expression? ' variable definition 1858
  var point name? = (3, 7)value or expression?;1859
- To refer to a 'value' in an enum, e.g.to pick one of the identifiers in the enum `SuitSuitSuitSuitSuit`:
  enum Suit Name? spades, hearts, diamonds, clubs values?values?1860
  class Suit Name?(Enum):
  spades = 1
  hearts = 2
  diamonds = 3
  clubs = 4 values?1861
  enum Suit Name? {spades, hearts, diamonds, clubs values?values?}1862
  Enum Suit Name?
  spades = 0
  hearts = 1
  diamonds = 2
  clubs = 3
  End Enum values?1863
  enum Suit Name? {spades, hearts, diamonds, clubs values?values?}1864
  variable suit name? set to Suit.spades value or expression?1865
  suit name? = Suit.spades value or expression? # variable definition 1866
  var suit name? = Suit.spades value or expression?;1867
  Dim suit name? = Suit.spades value or expression? ' variable definition 1868
  var suit name? = Suit.spades value or expression?;1869

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).

## 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 statement 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 statement 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 procedure call instruction

Valid forms for a procedure call are

- `call procedureNameprocedureName?(arguments?)60procedureNameprocedureName?(arguments?) # procedure call61procedureNameprocedureName?(arguments?); // procedure call62procedureNameprocedureName?(arguments?) ' procedure call63procedureNameprocedureName?(arguments?); // procedure call64` to call a library procedure, or user-defined procedure.
- `call instanceName.procedureMethodNameprocedureName?(arguments?)65instanceName.procedureMethodNameprocedureName?(arguments?) # procedure call66instanceName.procedureMethodNameprocedureName?(arguments?); // procedure call67instanceName.procedureMethodNameprocedureName?(arguments?) ' procedure call68instanceName.procedureMethodNameprocedureName?(arguments?); // procedure call69` to call a procedure method associated with a specific type using 'dot-syntax'.

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

For certain data structure types the name may be followed by a 'generic' clause, which specifies the types of the items that make up the data structure, for example:

`List<of Int>list[int]List<int>List(Of Integer)List<int>`
`Dictionary<of String, Int>Dictionary[str, int]Dictionary<string, int>Dictionary(Of String, Integer)Dictionary<String, int>` specifies that the keys are of type `StingStingStingStingSting` and the values of type `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 .