Elan Concepts

# Introduction

There are some concepts in the design of the Elan language and Integrated Development Environment which don't belong with any particular keyword or language construct described in the Language Reference or any particular data type or functionality in the Library Reference.

This Concepts document is the place for those descriptions and explanations.

##

# Language Features

## Named values

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

- mutable named values whose content can be assigned and re-assigned
- immutable named values whose content cannot be re-assigned, though they can be redefined

This distinction applies both to single values and to data structures and, while it is most pertinent in funcrional programing, it provides a useful discipline in any code.

## Named value Types

Elan's named values are statically typed: when initialised, their Type is established and cannot be changed.

The Types and their names as used in the language are here listed, linking to further detail:

| Mutable | Type name | notes
--- | --- | --- | ---
Fundamental Types |  |  |
Integer | ✘ | Int |
Floating point | ✘ | Float |
Boolean | ✘ | Boolean |
String | ✘ | String |
Group of values | see note | Tuple |
Mutable data structures |  |  |
Simple array | ✔ | Array |
2-dimensional array | ✔ | Array2D |
List | ✔ | List |
Look-up dictionary | ✔ | Dictionary |
Immutable data structures |  |  |
List | ✘ | ListImmutable |
Look-up dictionary | ✘ | DictionaryImmutable |
Set (maths like) | ✘ | Set |
LIFO Stack |  | Stack |
FIFO Quene |  | Queue |
Data I/O classes |  |  |
Text file input |  | TextFileReader |
Text file output |  | TextFileWriter |
Graphical |  |  |
Turtle |  | Turtle |
Vector graphic |  | VectorGraphic sub-types |
Other |  |  |
Random number |  | Random |
Function reference |  | Func |
User defined |  |  |
Application Class |  | (name of Class) |

### Re-assigning vs. mutating named values

define named value | named value | notes
--- | --- | ---
with | as mutable Type | as immutable Type | re-assign with 'set' | mutate | scope
constant | ✘ | ✔ | ✘ | ✘ | global | constant values are set only at compile time
let | ✔ |  | ✘ | ✔ | local |
let |  | ✔ | ✘ | ✘ | local |
variable | ✔ | ✔ | ✔ | ✔ | local |
parameter | ✔ |  | ✘ | ✔ | local | formal input argument of function, procedure or lambda
parameter |  | ✔ | ✘ | ✘ | local | formal input argument of function, procedure or lambda
out parameter | ✔ |  | ✔ | ✔ | local | formal output argument of procedure
out parameter |  | ✔ if actual argument defined with variable, not let | ✔ | ✔ | local | formal output argument of procedure

Names are given to all Types of such entities, whether simple data items (e.g. integer, Boolean) or data structures (e.g. array, class), and whether mutable or immutable.

### Mutables

You use variable statements to define the names and initial values of conventional variables (mutables), their values being specified either with literals or by evaluating expressions.

You can then use set statements to replace the values in mutables with new values, and there are methods to update standard mutable data structures.

### Immutables

You use let statements to define the names and fixed values of new immutables (their values also specified either with literals or by evaluating expressions).

Immutables are useful because they can:

- hold intermediate values for use in subsequent code, thus avoiding duplication
- help modularise a complex sequence of code

### Constants

For immutable values that are of use throughout your program, you can use constant statements (outside your procedures and functions) to set names and initialise fixed values that are accessible by all executable code in your program, i.e. they have global scope. Constants are defined either with literals or by reference to predefined class properties.

### Values at compilation and runtime

let, variable and set statements are used within your procedures and functions to take their values at execution time and so can be defined by literals or expressions. constant statements, by contrast, fix their values at compilation time.

### Scope

The scope or area of influence of named values is restricted to the procedures or functions within which they are defined.

### Values and programming style

It is good practice to make as many of your named values as possible immutable, either by defining them as constants or with let statements, or by making use of Elan's immutable data structures.

## Type Names

The Elan language has been carefully designed so that it supports static typing without the need for beginners to include the names of types in their programs. For example you can write a program that counts to 10 without using the type name "Int".

But there comes a point when you need to refer to the names of types when defining:

- the parameters of a function or procedure
- the return value of a function
- the properties of a record or class
- a variable with an empty value, for example an empty List
- a data type whose elements have a particular type, for example an Array<of Int>

The names of all the built-in types are specified in the Library Reference. You can create your own types as classes, records and enums.

## Method

We use the word "method" to describe functions and procedures in general.

## Dot method

There are many functions and procedures which belong to system-defined types or user-defined classes, and operate on an instance of that type or class.

For example the function asString can be invoked on an object instance molePosition like this:

if k is molePosition.asString() then

In this case, the variable molePosition is of type Int, and the Elan library provides the method asString.

A procedure may be invoked like this:

call holes.put(molePosition, "*")

The variable holes is of type Array<of String>, and the Elan library provides the method put for changing one element of an Array.

Functions and procedures that are defined as part of a user-defined class are also invoked from outside the class using a dot. For example a function:

set property.head to tail.getAdjacentSquare(property.currentDir)

and a procedure:

call apple.newRandomPosition(snake)

Collectively, these are known as dot methods. The functions and procedures that you define at a global level (ie not in a class or record) are not dot methods. There are also functions (eg abs) and procedures (eg clearPrintedText) provided by the Elan Library which are standalone. That is, they are not dot methods, and are used without a dot.

## Mutability

Some data structures are mutable and some are immutable.

The properties or contents of an instance of an immutable type may not be changed, directly. However, you can easily create another instance that is a copy of the original, with all the same property values except for any specific changes that you want to make. The newly-minted copy (with changes) must be assigned to a new, or the same, named value.

For examples of immutable types, see the five types described in the Immutable data structures section of the Library Reference. Strings are also immutable.

The simple value types (Int, Float and Boolean) are also effectively immutable. You can't change a single digit in a number in situ; you have to create a new number and assign it back to the original variable.

User-defined records are also immutable.

User-defined classes are always treated as mutable. For example, you cannot put instances of classes into a ListImmutable or DictionaryImmutable, or use them as keys in a Dictionary. This applies even if the class has no procedure members, so is effectively immutable in practice (but then you may as well use a record).

tuples cannot be directly changed once they have been made, for example you can't change just one element of a tuple. But tuples are allowed to contain mutable types, eg a List<of Int>, so they are actually treated as mutable.

The reason why mutability is of interest to computer scientists is that you can prove the correctness of programs more easily if they work with immutable data objects. It also can reduce the number of bugs in your code, and can allow more optimisations when running a program. It is widely used when writing code according to the functional programming paradigm.

## Static typing

Elan is a statically typed language. Every variable and parameter has a defined type.

For variables, the compiler can work out the type of the expression used to initialise the variable when it is declared. For example if you write this:

set n to 4

then the compiler defines the variable n to be of type Int, and only allows expressions of type Int to be assigned to it from there on.

For parameters, and properties in classes and records, the programmer has to write in the type name, eg "Int":

function willLive(cell as Int, liveNeighbours as Int) returns Boolean

The return type of every function is also defined, which enables the compiler to decide the type of every expression.

## Sound

To be written.

## Case sensitivity

As far as we know, everything in Elan is case-sensitive. That is, no case folding is done, and the upper and lower case versions of a letter count as different characters. When you refer to a method or variable that you have defined, you must spell it exactly the same as the definition.

If case folding is desired in a running program, you can do it explicitly by calling upperCase or lowerCase.

## Parsing

[I wrote this before discovering the Status panel section in the IDE Guide, which covers some of the same ground]

Automatically, as you type your code, the Integrated Development Environment parses it. That is, it scans through the code trying to make sense of what it sees. Initially, the line of code is incomplete, and the Parse status in the top right hand corner shows "incomplete" on an orange background. As you type more, eventually the line will be complete enough that the parse status changes to "valid" on a green background. At this point you can type some more if you wish: for example "set n to n" is valid, but you may actually want to say "set n to n + 1".

If you type something which could never be right, however much you add, the Parse status will go to "invalid" on a red background. Any part of the line can be changed to make it right: every time you change any character, the parser starts again and re-evaluates the situation.

For example, you may be trying to write "(n + 1)*2" but initially forget about the brackets and type "n + 1", then remember the brackets and type "n + 1)". At this point it goes red, but don't be fazed: it is fine to go back to the start of the field, using the mouse or the left-arrow key, and change it to "(n + 1)", and at that point it will go green again.

## Compilation

Once the Parse status is valid, the compilation stage starts. The result is one of:

- "ok" on a green background
- "unknown" on an orange background
- "error" on a red background

In either of the error states, you can click on the coloured status and it will scroll the code window to (one of) the error(s). Clicking on the erroneous line should give further information as to what the problem is. If the message is unhelpful, please let us know how it can be improved.

The unknown status usually appears if there is a name which it does not recognise. There is not much difference in practice between the "unknown" and "error" states. In neither case can the program be run.

The idea is that the "error" state can usually be corrected by editing the line with the error, but the "unknown" state may need another variable, function etc defining before it is resolved.

Elan Concepts go to the top