EK9 in Depth
Built-in Types at a Glance
Every type here is in the org.ek9.lang module and needs no references. This appendix is a map, one line per type; the
authority for any one of them is the compiler's own help, ek9 -h <Type>, which lists every constructor, method and
operator of the type and is generated from the runtime. ek9 -H lists every keyword, the built-in types among them. Every
type is tri-state: it can be set, unset or absent, and ? asks whether it is set (Values and the Three States). Collections
are the one place where that differs by type: a list or dictionary is set the moment it exists, empty or not.
Values
| Type |
What it is |
Written as |
Boolean |
logical true or false; and, or, xor, not |
true, false |
Character |
one Unicode character |
'A', '\n' |
String |
Unicode text; +, length, contains, matches |
"hello", `Hello ${name}` |
Integer |
64-bit signed whole number; overflow gives unset, never a wrapped value |
42, 0x1F, 1_000 |
Float |
64-bit IEEE 754; <~> is the fuzzy comparison |
3.25, -2.5e10 |
Money |
exact decimal currency, so never a Float |
25.99#GBP |
Bits |
variable-length bit sequence; and, or, xor, ~, shifts; + joins |
0b1010 |
Byte |
unsigned 8-bit value with no arithmetic; out of range is unset |
Byte(255) |
Bytes |
immutable binary data; the literal is hex digits in pairs |
0yDEADBEEF |
BytesBuilder |
the mutable write side of Bytes |
BytesBuilder() |
BytesReader |
forward-only cursor over Bytes; a read past the end is unset |
aBytes.reader() |
Colour |
RGB or ARGB colour |
#FF5500 |
Dimension |
a size with its unit |
42.5km, 1920px |
Resolution |
dots per inch or per centimetre |
300dpi, 118dpc |
Locale |
language and region |
Locale("en_GB") |
Version |
semantic version |
1.2.3-0 |
GUID |
a UUID; GUID() makes a new one |
GUID() |
RegEx |
a regular expression with its own literal |
/[a-z]+/ |
Path |
a JSONPath, an address into structured data and not a file path |
$?.store.book[0].title |
Void |
"no return value" in a signature; not a variable type |
|
One program holds a literal of every type that has one, and prints each. It is the quickest way to see the forms:
defines module book.types.literals
defines program
Literals()
stdout <- Stdout()
truth <- true
letter <- 'A'
text <- "hello"
count <- 1_000
hexCount <- 0x1F
ratio <- 3.25
bits <- 0b1010
octets <- 0yDEADBEEF
shade <- #FF5500
day <- 2024-01-15
moment <- 2024-01-15T10:30:00Z
clockTime <- 10:30:00
span <- PT1H30M
short <- 500ms
price <- 25.99#GBP
distance <- 42.5km
density <- 300dpi
locale <- Locale("en_GB")
release <- 1.2.3-0
address <- $?.store.book[0].title
pattern <- /[a-z]+/
names <- ["Ada", "Grace"]
ages <- {"Ada": 36, "Grace": 85}
stdout.println(`boolean ${truth}, character ${letter}, string ${text}`)
stdout.println(`integer ${count}, hexadecimal ${hexCount}, float ${ratio}`)
stdout.println(`bits ${bits}, bytes ${octets}, colour ${shade}`)
stdout.println(`date ${day}, datetime ${moment}, time ${clockTime}`)
stdout.println(`duration ${span}, millisecond ${short}, money ${price}`)
stdout.println(`dimension ${distance}, resolution ${density}, locale ${locale}`)
stdout.println(`version ${release}, path ${address}, regex ${pattern}`)
stdout.println(`list ${names}, dict ${ages}`)
boolean true, character A, string hello
integer 1000, hexadecimal 31, float 3.25
bits 1010, bytes DEADBEEF, colour #FF5500
date 2024-01-15, datetime 2024-01-15T10:30:00Z, time 10:30:00
duration PT1H30M, millisecond 500ms, money 25.99#GBP
dimension 42.5km, resolution 300dpi, locale en_GB
version 1.2.3-0, path $?.store.book[0].title, regex [a-z]+
list ["Ada", "Grace"], dict {Ada=36, Grace=85}
Three of the forms surprise people from other languages. Money is written with the currency after the amount,
25.99#GBP; a bare version such as 1.2.3 does not parse, because the literal always carries its build number
(1.2.3-0); and a locale has no literal - it is made with Locale("en_GB"). The values on the right of the table are
the ones the example above compiles.
Time
| Type |
What it is |
Written as |
Time |
time of day |
10:30:00 |
Date |
calendar date |
2024-01-15 |
DateTime |
date and time with a zone |
2024-01-15T10:30:00Z |
Duration |
a span, ISO 8601 |
PT1H30M |
Millisecond |
a short span in milliseconds |
500ms |
SystemClock |
the system time source; the implementation of the Clock trait; a test supplies a fixed clock |
SystemClock() |
Collections and containers
| Type |
What it is |
List of T |
ordered, indexable; [1, 2, 3]; += adds |
Dict of (K, V) |
key to value; {"a": 1}; iterating yields DictEntry |
DictEntry of (K, V) |
one pair from a dictionary; key() and value() |
PriorityQueue of T |
heap ordered by <=>, so T must be comparable |
Iterator of T |
lazy sequence; hasNext() before next(); a stream source |
Optional of T |
zero or one value; get() only in a checked block (Optional and Result, in Depth) |
Result of (O, E) |
an ok value, an error value, both or neither (Optional and Result, in Depth) |
| Type |
What it is |
Stdout, Stderr |
println and print; accept anything with a $ operator |
Stdin |
standard input as lines; hasNext() and next(), and a stream source |
TextFile |
set only when its path is absolute and names an existing file; opened for input() or output() in a try |
FileSystem |
cwd() and tmp(), each a FileSystemPath |
FileSystemPath |
a platform-independent path, with the file operations |
JSON |
a JSON document; JSON().parse(text) gives a Result of (JSON, String), and $$ serialises any type |
GetOpt |
command-line option parser |
OS |
process id, delay, non-cryptographic random numbers |
EnvVars |
environment variables, sanitised by default; sensitiveGet returns a Sensitive |
Signals |
operating-system signal handlers |
Exception |
the base of every exception, open for your own; reason() and exitCode() (Errors and Exceptions) |
Network, concurrency and security
| Type |
What it is |
TCP, UDP |
sockets, both made in a try from a NetworkProperties (Networking: TCP and UDP) |
MutexLock of T |
mutual exclusion around a value, entered with a MutexKey of T (Concurrency, Safely) |
Digest |
unkeyed SHA256 and SHA512: integrity only |
HMAC |
a keyed code over Bytes: integrity and authenticity |
SecureRandom |
cryptographically secure random octets as Bytes, deliberately not a Random |
InputSanitizer |
what the sanitized modifier uses; write sanitized, not a call (A Web Service, Step by Step) |
When a type you expect from another language is missing from the tables, look for the operator before you look for a type:
a == b, a <=> b, $ a, #? a and target :=: source stand where equals, compareTo, toString, hashCode and
clone would (Operators and Pragmatic Purity, in Full), and ek9 -h <Type> prints the constructors, so there is never a
need to guess whether a type can be made from a String.