Skip to content

Expressions in EK

Lindon Aliu edited this page Jan 29, 2024 · 1 revision

There are not that many expressions in EK, but they are very powerful. This section will cover all of the expressions in EK.

Literals

There are two types of literals in EK: numbers and strings.

Integers

Integers are written as a sequence of digits. For example, 123 is an integer. You can also use a leading - to make the integer negative, like this: -123.

Floats

Floats are written as a sequence of digits, with a period in the middle. For example, 13.5 is a float. You can also use a leading - to make the float negative, like this: -5.0.

Strings

Strings are written as a sequence of characters surrounded by double quotes. For example, "Hello, world!" is a string.

You can also use escape sequences in strings. For example, \n is a newline, and \t is a tab. You can also use \ to escape a double quote, like this: \".

Calls

Calls are used to call functions. They are written according to the pattern of the function. For example, to call a prefix function f _, you can write f x. To call an infix function _ f _, you can write x f y. To call a postfix function _ f, you can write x f.

For functions with no arguments, you will just write the name of the function.

Arguments to a function work like functions with no arguments.

fn f (x) = x

Here, the body of the function is x, which calls the argument x. If the argument was marked as lazy, it could have side effects.

Lambda expressions

Lambda expressions are used to create functions, which may capture variables from the surrounding scope. They are written beginning with a \, followed by a list of argument names, followed by an =, followed by the body of the lambda function.

For example, the identity function can be written as \x = x. To call this function, you can then use the _ $ _ function defined in the std module.

import std
fn id = \x = x
fn main = print (id $ 1)

This will print 1.

Because lambdas are closures, they can capture variables from the surrounding scope. You can for example write a function that adds a constant to a number like this:

fn add (x) = \y = x + y
fn main = print (add 1 $ 2)

Partial application

Partial application is used to create a new function from an existing function by applying only some of its arguments. It is written using the _ placeholder. For example, to create a function that adds 1 to a number, you can write:

fn inc = _ + 1

This will create a new function that takes one argument and adds 1 to it. You can then call it like this:

fn main = print (inc $ 1)

Placeholders can be used in any position in a function call. Note that the placeholder value creates a function, so it cannot be 'chain-called' like a normal function. For example, this is invalid:

fn f _ = 2 * _ + 1

This is because 2 * _ is a function, and the + 1 cannot be applied to it. Instead, you can write the following alternatives:

fn f _ = \x = 2 * x + 1
fn f (x) = 2 * x + 1
fn f _ = (_ + 1) . (2 * _) 

The last one uses the composition operator _ . _, which is defined in the std module.

Type Checks

Type checks are used to check the type of a value. They are written using the is keyword, followed by the type to check for. For example, to check if a value is an integer, you can write value is int. Type checks can be used in if, like this:

fn main = if 1 is int then print "It's an integer!" else print "It's not an integer!"

Any type can be used in a type check, including user-defined types, and int ranges.

fn info (v) = if v is [0..] then "positive" else "negative"

More information about types can be found in the Types in EK section.

List expression

List expressions are used to create lists. They are written as a comma-separated list of values surrounded by square brackets. For example, [1, 2, 3] is a list of integers. Lists can contain any type of value, including other lists. For example, [[1, 2], [3, 4]] is a list of lists of integers. To use it, you have to import the list module.

import list

fn main = print [1, 2, 3]

Clone this wiki locally