https://danolearn.com/en/ucode/quick-sort-59119
use aiken/list fn quicksort(xs: List<Int>) -> List<Int> { when xs is { [] -> [] [p, ..tail] -> { let before = tail |> list.filter(fn(x) { x < p }) |> quicksort let after = tail |> list.filter(fn(x) { x >= p }) |> quicksort list.concat(before, [p, ..after]) } } } test quicksort_0() { quicksort([]) == [] } test quicksort_1() { quicksort([3, 2, 1, 4]) == [1, 2, 3, 4] } test quicksort_2() { quicksort([1, 2, 3, 4]) == [1, 2, 3, 4] }
ar = [1, 2, 3]
for i in (0, len(ar)):
ar[i] = ar[i] * 2
vs
ar = [1, 2, 3].map(v => v * 2)
Pros
Cons
list
bytearray
dict
let x = 1
let y: Int = x // Type annotations
let x = 2 // shadows previous bindings
const start_year = 2001 /* module constant */
const end_year = 2011
#define
in C/C++.42
, 14
, 1_000_000
+
, -
, *
, /
(integer division), *
, %
==
, >
, <
, >=
, <=
True
, False
==
, &&
, ||
, !
0
to 255
)
"foo"
#[102, 111, 111]
#[0x66, 0x6f, 0x6f]
#"666f6f"
(10, "hello")
(Int, ByteArray)(1, 4, [0])
(Int, Int, List<Int>)let point = (14, 42, 1337, 0)
let a = point.1st
let b = point.2nd
let c = point.3rd
let d = point.4th
(c, d, b, a) // (1337, 0, 42, 14)
let x = [2, 3] // all data structures are immutable
let y = [1, ..x] // inserting at the front of list x
x // [2, 3]
y // [1, 2, 3]
let result =
dict.new()
|> dict.insert(key: "a", value: 100)
|> dict.insert(key: "b", value: 200)
|> dict.delete(key: "a")
|> dict.to_pairs()
result == [Pair("b", 200)]
/// Document here
/// Named function, with type annotations
fn add(x: Int, y: Int) -> Int {
x + y // no explicit return keyword
}
fn run() {
let add = fn(x, y) { x + y } // anonymous function
add(1, 2)
}
fn replace(self: String, pattern: String,
replacement: String) {
// ...
}
replace(self: @"A,B,C", pattern: @",", replacement: @" ")
// Labeled arguments can be given in any order
replace(pattern: @",", replacement: @" ", self: @"A,B,C")
// Positional arguments and labels can be mixed
replace(@"A,B,C", pattern: @",", replacement: @" ")
Pipe operator: |>
- passing the result of one function to the arguments of another function.
string_builder.to_string(
string_builder.reverse(
string_builder.from_string(s)
)
)
s
|> string_builder.from_string
|> string_builder.reverse
|> string_builder.to_string
fn add(x: Int , y: Int ) -> Int {
x + y
}
fn run() {
// This is the same as add(add(add(1, 3), 6), 9)
// `_` indicates where the argument should be passed.
1
|> add(_, 3)
|> add(_, 6)
|> add(_, 9)
// shorthand
1
|> add(3)
|> add(6)
|> add(9)
}
/// Type variable `a` is used to represent
/// any possible type.
fn list_of_two(my_value: a) -> List<a> {
[my_value, my_value]
}
/// To write a unit test, use the `test` keyword:
test foo() {
1 + 1 == 2 // a test returns a boolean
}
https://danolearn.com/en/ucode/add-one-59120
fn add_one(n: Int) -> Int {
n + 1
}
test add_one_1() {
add_one(0) == 1
}
test add_one_2() {
add_one(-42) == -41
}
if else
when {expr} is
Every block in Aiken is an expression with the value of the last expression in that block.
let value: Bool = {
"Hello"
42 + 12
False
}
value == False
if else
fn fibonacci(n: Int) -> Int {
if n == 0 {
0
} else if n == 1 {
1
} else {
fibonacci(n-2) + fibonacci(n-1)
}
}
when {expr} is
when a is {
0 -> "Zero"
1 -> "One"
2 -> "Two"
n -> "Some other number" // This matches anything
}
when xs is {
[] -> "This list is empty"
[a] -> "This list has 1 element"
[a, b] -> "This list has 2 elements"
_other -> "This list has more than 2 elements"
}
aiken/math
aiken/int
aiken/interval
aiken/list
aiken/bytearray
aiken/dict
use
.use unix/dog use animal/dog as kitty // named import
use animal/dog.{Dog, stroke}
pub fn foo() {
let puppy = Dog { name: "Zeus" }
stroke(puppy)
}
aiken/math
abs(self: Int) -> Int
gcd(x: Int, y: Int) -> Int
max(a: Int, b: Int) -> Int
min(a: Int, b: Int) -> Int
pow(self: Int, e: Int) -> Int
sqrt(self: Int) -> Option<Int>
list
length(self: List<a>) -> Int
count(self: List<a>, predicate: fn(a) -> Bool) -> Int
list.length([]) == 0
list.length([1, 2, 3]) == 3
list.count([], fn(a) { a > 2}) == 0
list.count([1, 2, 3], fn(a) { a >= 2 }) == 2
list.count([1, 2, 3], fn(a) { a > 5 }) == 0
all(self: List<a>, predicate: fn(a) -> Bool) -> Bool
any(self: List<a>, predicate: fn(a) -> Bool) -> Bool
list.all([], fn(n) { n > 0 }) == True
list.all([1, 2, 3], fn(n) { n > 0 }) == True
list.all([1, 2, 3], fn(n) { n == 2 }) == False
// 0-based index
at(self: List<a>, index: Int) -> Option<a>
head(self: List<a>) -> Option<a>
last(self: List<a>) -> Option<a>
push(self: List<a>, elem: a) -> List<a>
delete(self: List<a>, elem: a) -> List<a>
use aiken/option
list.at([1, 2, 3], 1) == Some(2)
list.at([1, 2, 3], 42) == None
list.head([1, 2, 3]) == Some(1)
list.last([1, 2, 3]) == Some(3)
// insert in front
list.push([2, 3], 1) == [1, ..[2, 3]] == [1, 2, 3]
// Remove the first occurrence of 1
list.delete([1, 2, 3, 1], 1) == [2, 3, 1]
list.delete([1, 2, 3], 14) == [1, 2, 3]
option.or_else(list.at([1, 2, 3], 1), 0) == 2
concat(left: List<a>, right: List<a>) -> List<a>
slice(self: List<a>, from: Int, to: Int) -> List<a>
init(self: List<a>) -> Option<List<a>>
tail(self: List<a>) -> Option<List<a>>
list.concat([1, 2, 3], [4, 5, 6])
== [1, 2, 3, 4, 5, 6]
list.slice([1, 2, 3, 4, 5, 6], from: 2, to: 4)
== [3, 4, 5]
list.slice([1, 2, 3, 4, 5, 6], from: -2, to: -1)
== [5, 6]
list.init([1, 2, 3]) == Some([1, 2])
list.tail([1, 2, 3]) == Some([2, 3])
take(self: List<a>, n: Int) -> List<a>
drop(self: List<a>, n: Int) -> List<a>
span(self: List<a>, n: Int) -> (List<a>, List<a>)
list.take([1, 2, 3], 2) == [1, 2]
list.drop([1, 2, 3], 2) == [3] // drop first 2 items
// span(xs, n) == (take(xs, n), drop(xs, n))
span([1, 2, 3, 4, 5], 3) == ([1, 2, 3], [4, 5])
has(self: List<a>, elem: a) -> Bool
find(self: List<a>, predicate: fn(a) -> Bool) -> Option<a>
index_of(self: List<a>, elem: a) -> Option<Int>
list.has([1, 2, 3], 2) == True
list.has([1, 2, 3], 14) == False
// find first item that >= 2
list.find([1, 2, 3], fn(x) { x >= 2 }) == Some(2)
list.find([4, 5, 6], fn(x) { x == 2 }) == None
list.index_of([1, 7, 3], 4) == None
list.index_of([1, 0, 9, 6], 6) == 3
sort(self: List<a>, compare: fn(a, a) -> Ordering) -> List<a>
use aiken/int
sort([3, 1, 4, 0, 2], int.compare) == [0, 1, 2, 3, 4]
sort([1, 2, 3], int.compare) == [1, 2, 3]
filter(self: List<a>, predicate: fn(a) -> Bool)
-> List<a>
partition(self: List<a>, predicate: fn(a) -> Bool)
-> (List<a>, List<a>)
drop_while(self: List<a>, predicate: fn(a) -> Bool)
-> List<a>
take_while(self: List<a>, predicate: fn(a) -> Bool)
-> List<a>
list.filter([1, 2, 3], fn(x) { x >= 2 }) == [2, 3]
list.partition([1, 2, 3, 4], fn(x) { x % 2 == 0 })
== ([2, 4], [1, 3])
list.drop_while([1, 2, 3], fn(x) { x <= 2 }) == [3]
list.take_while([1, 2, 3], fn(x) { x <= 2 }) == [1, 2]
map(self: List<a>, with: fn(a) -> result)
-> List<result>
map2(self: List<a>, bs: List<b>, with: fn(a, b) -> result)
-> List<result>
map3(
self: List<a>, bs: List<b>, cs: List<c>,
with: fn(a, b, c) -> result,
) -> List<result>
list.map([1, 2, 3, 4], fn(n) { n + 1 }) == [2, 3, 4, 5]
list.map2([1, 2, 3], [1, 2], fn(a, b) { a + b }) == [2, 4]
list.map3(
[1, 2, 3], [1, 2], [1, 2, 3],
fn(a, b, c) { a + b + c }
) == [3, 6]
sum
, product
, max
, min
, concat_all
reverse
foldl(self: List<a>, zero: b, with: fn(a, b) -> b) -> b
// (3 + (2 + (1 + 0)))
list.foldl([1, 2, 3], 0, fn(n, total) { n + total })
== 6
// [3, ..[2, ..[1, ..[]]]]
list.foldl([1, 2, 3], [], fn(x, xs) { [x, ..xs] })
== [3, 2, 1]
foldr(self: List<a>, zero: b, with: fn(a, b) -> b) -> b
// (1 + (2 + (3 + 0)))
list.foldr([1, 2, 3], 0, fn(n, total) { n + total })
== 6
// [1, ..[2, ..[3, ..[]]]]
list.foldr([1, 2, 3], [], fn(x, xs) { [x, ..xs] })
== [1, 2, 3]
reduce(self: List<a>, zero: b, with: fn(b, a) -> b) -> b
list.reduce([#[1], #[2], #[3]], #[0], bytearray.concat)
== #[0, 1, 2, 3]
bytearray
& dict