2022-03-03 16:10:47 +03:00
|
|
|
---
|
|
|
|
slug: syntax
|
|
|
|
---
|
|
|
|
|
2022-01-14 16:56:39 +03:00
|
|
|
# Nickel Syntax
|
|
|
|
|
2022-06-16 18:59:42 +03:00
|
|
|
## Identifiers
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Nickel identifiers start with an alphabetic character, followed by zero or more
|
|
|
|
alphanumeric characters, `_` (underscores) or `'` (single quotes). For example,
|
|
|
|
`this-isn't-invalid` is a valid identifier.
|
2022-06-16 18:59:42 +03:00
|
|
|
|
2022-01-20 13:47:05 +03:00
|
|
|
## Simple values
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-03-08 13:22:31 +03:00
|
|
|
There are four basic kind of values in Nickel :
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
1. numeric values
|
|
|
|
2. boolean values
|
|
|
|
3. strings
|
|
|
|
4. enum tags
|
2022-03-03 16:10:47 +03:00
|
|
|
|
2022-01-14 16:56:39 +03:00
|
|
|
### Numeric values
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Nickel has a support for numbers, positive and negative, with or without
|
|
|
|
decimals. Internally, those numbers are stored as 64-bits floating point
|
|
|
|
numbers, following the IEEE 754 standard.
|
2022-01-14 16:56:39 +03:00
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
2022-03-07 14:27:09 +03:00
|
|
|
```nickel
|
2022-01-14 16:56:39 +03:00
|
|
|
1
|
|
|
|
0.543
|
|
|
|
42
|
|
|
|
-1000000
|
|
|
|
-6.8
|
|
|
|
```
|
|
|
|
|
|
|
|
There are a some predefined operators for working with numbers :
|
|
|
|
| Operator | Description | Example |
|
|
|
|
|:--------:|:----------------------------------------------------:|:-------------:|
|
|
|
|
| + | The addition operator | `1 + 2 = 3` |
|
|
|
|
| \- | The subtraction operator | `1 - 2 = -1` |
|
|
|
|
| * | The multiplication operator | `1 * 2 = 2` |
|
|
|
|
| / | The division operator | `1 / 2 = 0.5` |
|
|
|
|
| % | The modulo operator (returns the *signed* remainder) | `5 % 3 = 2` |
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
> **Remark about the `-` operator:** Since `-` can be used inside an identifier,
|
|
|
|
> the subtraction operators **needs** to be surrounded by spaces: write `a - b`,
|
|
|
|
> not `a-b`. `1-2` works as expected, because `1` and `2` aren't identifiers.
|
2022-01-20 15:24:53 +03:00
|
|
|
|
2022-01-25 14:45:20 +03:00
|
|
|
Numbers can be compared using the following operators :
|
2022-01-14 16:56:39 +03:00
|
|
|
| Operator | Description | Example |
|
|
|
|
|:--------:|:----------------:|:---------:|
|
|
|
|
| == | Equal | `5 == 5` |
|
|
|
|
| != | Not Equal | `5 != 4` |
|
|
|
|
| < | Smaller than | `2 < 3` |
|
|
|
|
| > | Greater than | `1 > -5` |
|
|
|
|
| >= | Greater or Equal | `1 >= 1` |
|
|
|
|
| <= | Smaller or Equal | `-1 <= 6` |
|
|
|
|
|
2022-01-25 14:45:20 +03:00
|
|
|
In the table below, you will find the operators sorted from highest to lowest precedence:
|
2022-01-20 15:24:53 +03:00
|
|
|
| Operators | Associativity | Remark |
|
|
|
|
|:--------------------:|:-------------:|-----------------------------------------------|
|
2022-01-25 14:45:20 +03:00
|
|
|
| `( ... )` | | parentheses always have the highest precedence |
|
2022-02-07 15:19:35 +03:00
|
|
|
| `-` | | unary negation (as in `-1`) |
|
2022-01-20 15:24:53 +03:00
|
|
|
| `*`, `/`, `%` | left-to-right | |
|
|
|
|
| `+`, `-` | left-to-right | binary addition and subtraction |
|
|
|
|
| `<`, `>`, `=<`, `>=` | left-to-right | |
|
|
|
|
| `==`, `!=` | left-to-right | |
|
2022-01-14 16:56:39 +03:00
|
|
|
|
|
|
|
### Boolean values
|
|
|
|
|
|
|
|
The boolean values in Nickel are denoted `true` and `false`.
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Nickel features the classical boolean operators *AND* (&&), *OR* (||) and *NOT*
|
|
|
|
(!). The *AND* and *OR* operators are lazy in the evaluation of the second
|
|
|
|
argument: for example, in `exp1 && exp2`, `exp2` is only evaluated if `exp1`
|
|
|
|
evaluates to `false`.
|
2022-01-14 16:56:39 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-14 16:56:39 +03:00
|
|
|
> true && false
|
|
|
|
false
|
|
|
|
|
|
|
|
> false || true
|
|
|
|
true
|
|
|
|
|
|
|
|
> ! true
|
|
|
|
false
|
|
|
|
```
|
|
|
|
|
|
|
|
### Strings
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Nickel can work with sequences of characters, or strings. Strings are enclosed
|
|
|
|
by `" ... "` for a single line string or by `m%" ... "%m` for a multiline
|
|
|
|
string. They can be concatenated with the operator `++`. Strings must be UTF-8
|
|
|
|
valid.
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
The string interpolation syntax is
|
|
|
|
`"%{ < expression that evaluates to a string > }"`.
|
2022-01-24 12:31:05 +03:00
|
|
|
|
2022-01-14 16:56:39 +03:00
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-14 16:56:39 +03:00
|
|
|
> "Hello, World!"
|
|
|
|
"Hello, World!"
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> m%"Well, if this isn't a multiline string?
|
|
|
|
Yes it is, indeed it is"%m
|
2022-01-14 16:56:39 +03:00
|
|
|
"Well, if this isn't a string?
|
|
|
|
Yes it is, indeed it is"
|
|
|
|
|
2022-01-27 16:36:52 +03:00
|
|
|
> "Hello" ++ "World"
|
|
|
|
"HelloWorld"
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> let h = "Hello" in "%{h} World"
|
2022-01-27 16:36:52 +03:00
|
|
|
"Hello World"
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> let n = 5 in "The number %{n}."
|
2022-01-27 16:36:52 +03:00
|
|
|
error: Type error
|
|
|
|
|
2022-03-02 14:00:42 +03:00
|
|
|
> let n = 5 in "The number %{string.from_num n}."
|
2022-01-27 16:36:52 +03:00
|
|
|
"The number 5."
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Multiline strings are useful to write indented lines. The indentation is
|
|
|
|
stripped from the beginning of the first line, and first and last lines are
|
|
|
|
ignored if they are empty or contain only spaces.
|
2022-01-27 16:36:52 +03:00
|
|
|
|
|
|
|
Example:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-02-24 11:34:55 +03:00
|
|
|
> m%"
|
2022-05-18 04:21:10 +03:00
|
|
|
This line has no indentation.
|
2022-01-25 15:25:10 +03:00
|
|
|
This line is indented.
|
|
|
|
This line is even more indented.
|
2022-05-18 04:21:10 +03:00
|
|
|
This line has no more indentation.
|
2022-02-24 11:34:55 +03:00
|
|
|
"%m
|
2022-01-25 15:25:10 +03:00
|
|
|
"This line has no indentation.
|
|
|
|
This line is indented.
|
|
|
|
This line is even more indented.
|
2022-03-03 16:10:47 +03:00
|
|
|
This line has no more indentation."
|
2022-01-27 16:36:52 +03:00
|
|
|
```
|
2022-01-25 15:25:10 +03:00
|
|
|
|
2022-01-27 16:36:52 +03:00
|
|
|
The only special sequence in a multiline string is the string interpolation.
|
2022-01-24 12:31:05 +03:00
|
|
|
|
2022-01-27 16:36:52 +03:00
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-02-24 11:34:55 +03:00
|
|
|
> m%"Multiline\nString?"%m
|
2022-01-27 16:36:52 +03:00
|
|
|
"Multiline\nString?"
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> m%"Multiline%{"\n"}String"%m
|
2022-01-27 16:36:52 +03:00
|
|
|
"Multiline
|
|
|
|
String"
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
A multiline string can be introduced and closed by multiple `%` signs, as long
|
|
|
|
as this amount is equal. If you want to use string interpolation, you must use
|
|
|
|
the same amount of `%` as in the delimiters.
|
2022-01-27 16:36:52 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-02-24 11:34:55 +03:00
|
|
|
> m%%"Hello World"%%m
|
2022-01-24 12:31:05 +03:00
|
|
|
"Hello World"
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> m%%%%%"Hello World"%%%%%m
|
2022-01-27 16:36:52 +03:00
|
|
|
"Hello World"
|
2022-01-24 12:31:05 +03:00
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> let w = "World" in m%%"Hello %{w}"%%m
|
|
|
|
"Hello %{w}"
|
2022-01-27 16:36:52 +03:00
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> let w = "World" in m%%"Hello %%{w}"%%m
|
2022-01-27 16:36:52 +03:00
|
|
|
"Hello World"
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Multiline strings are "indentation-aware". This means that one could use an
|
|
|
|
indented string interpolation and the indentation would behave as expected:
|
2022-02-23 13:32:10 +03:00
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
```text
|
2022-02-24 11:34:55 +03:00
|
|
|
> let log = m%"
|
2022-01-27 16:36:52 +03:00
|
|
|
if log:
|
|
|
|
print("log:", s)
|
2022-02-24 11:34:55 +03:00
|
|
|
"%m in m%"
|
2022-02-23 13:32:10 +03:00
|
|
|
def concat(str_array, log=false):
|
2022-01-27 16:36:52 +03:00
|
|
|
res = []
|
2022-02-23 13:32:10 +03:00
|
|
|
for s in str_array:
|
2022-02-24 11:34:55 +03:00
|
|
|
%{log}
|
2022-01-27 16:36:52 +03:00
|
|
|
res.append(s)
|
|
|
|
return res
|
2022-02-24 11:34:55 +03:00
|
|
|
"%m
|
2022-02-23 13:32:10 +03:00
|
|
|
"def concat(str_array, log=false):
|
2022-01-27 16:36:52 +03:00
|
|
|
res = []
|
2022-02-23 13:32:10 +03:00
|
|
|
for s in str_array:
|
2022-01-27 16:36:52 +03:00
|
|
|
if log:
|
|
|
|
print("log:", s)
|
|
|
|
res.append(s)
|
|
|
|
return res"
|
2022-01-14 16:56:39 +03:00
|
|
|
```
|
|
|
|
|
2022-03-08 13:22:31 +03:00
|
|
|
#### Enum tags
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Enumeration tags are used to express finite alternatives. They are formed by
|
|
|
|
writing a backtick `` ` `` followed by any valid identifier. For example,
|
2022-03-08 13:22:31 +03:00
|
|
|
`builtin.serialize` takes an export format as a first argument, which is an enum
|
|
|
|
tag among `` `Json ``, `` `Toml `` or `` `Yaml `` (as of version 0.1):
|
|
|
|
|
|
|
|
```nickel
|
|
|
|
builtin.serialize `Json {foo = 1}
|
|
|
|
# gives "{
|
|
|
|
# \"foo\": 1
|
|
|
|
# }"
|
|
|
|
builtin.serialize `Toml {foo = 1}
|
|
|
|
# gives "foo = 1
|
|
|
|
# "
|
|
|
|
```
|
|
|
|
|
|
|
|
An enum tag `` `foo `` is serialized as the string `"foo"`:
|
|
|
|
|
|
|
|
```nickel
|
|
|
|
let as_yaml_string = builtin.serialize `Yaml {foo = `bar}
|
|
|
|
# gives "---
|
|
|
|
# foo: bar
|
|
|
|
# "
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
While it's technically possible to just use strings in place of enum tags, using
|
|
|
|
an enum tag insists on the fact that only a finite number of alternatives can be
|
|
|
|
used for the corresponding value.
|
|
|
|
|
2022-07-28 20:07:48 +03:00
|
|
|
Additionally, the typechecker is aware of enums and can for example statically
|
|
|
|
enforce that only valid tags are passed to a function within a typed block. See
|
|
|
|
[the manual section on typing](./typing.md) for more details.
|
2022-03-08 13:22:31 +03:00
|
|
|
|
2022-02-07 15:19:35 +03:00
|
|
|
## Equality
|
2022-01-17 16:04:22 +03:00
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Operators `==` and `!=` are used to compare values. Two values of different
|
|
|
|
types are never equal: that is, `==` doesn't perform implicit conversions.
|
2022-01-17 16:04:22 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-17 16:04:22 +03:00
|
|
|
> 1 == 1
|
|
|
|
true
|
|
|
|
|
|
|
|
> 5 == 5.0
|
|
|
|
true
|
|
|
|
|
|
|
|
> "Hello" == "Hello"
|
|
|
|
true
|
|
|
|
|
|
|
|
> "Hello" != "World"
|
|
|
|
true
|
|
|
|
|
|
|
|
> 5 == "Hello"
|
|
|
|
false
|
|
|
|
|
|
|
|
> true == "true"
|
|
|
|
false
|
|
|
|
```
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-01-20 13:47:05 +03:00
|
|
|
## Composite values
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-03-03 16:10:47 +03:00
|
|
|
### Array
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
An array is a sequence of values. They are delimited by `[` and `]`, and
|
|
|
|
elements are separated with `,`.
|
2022-01-17 16:08:31 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
2022-03-07 14:27:09 +03:00
|
|
|
```nickel
|
2022-01-17 16:08:31 +03:00
|
|
|
[1, 2, 3]
|
|
|
|
["Hello", "World"]
|
|
|
|
[1, true, "true"]
|
|
|
|
[]
|
|
|
|
```
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-02-23 13:32:10 +03:00
|
|
|
Arrays can be concatenated with the operator `@`:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-17 18:45:35 +03:00
|
|
|
> [1] @ [2, 3]
|
|
|
|
[ 1, 2, 3 ]
|
|
|
|
```
|
|
|
|
|
2022-01-14 16:56:39 +03:00
|
|
|
### Record
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
Records are key-value storage, or in Nickel terms, field-value storage. They are
|
|
|
|
delimited by `{` and `}`, and elements are separated with `,`. Field-value
|
|
|
|
elements are noted as `field = value`. The fields are strings, but can be
|
|
|
|
written without quotes `"` if they respect identifiers syntax. Values can be of
|
|
|
|
any type. Elements inside a record are unordered. Two records can be *merged*
|
|
|
|
together using the operator `&`. The reader can find more information about
|
|
|
|
merging in the [section on merging](./merging.md).
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-01-17 18:45:35 +03:00
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
2022-03-07 14:27:09 +03:00
|
|
|
```nickel
|
2022-01-17 18:45:35 +03:00
|
|
|
{}
|
|
|
|
{a = 3}
|
2022-02-07 15:35:52 +03:00
|
|
|
{my_id_n5 = "my id number 5", "my id n4" = "my id number 4" }
|
2022-01-17 18:45:35 +03:00
|
|
|
{"5" = 5, six = 6}
|
|
|
|
```
|
|
|
|
|
|
|
|
Accessing a record field can be done using the `.` operator :
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-17 18:45:35 +03:00
|
|
|
> { a = 1, b = 5 }.a
|
|
|
|
1
|
|
|
|
|
|
|
|
> { a = 1 }.b
|
|
|
|
error: Missing field
|
|
|
|
|
|
|
|
> { "1" = "one" }."1"
|
|
|
|
"one"
|
|
|
|
```
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
It is possible to write records of records via the *piecewise syntax*, where we
|
|
|
|
separate fields by dots:
|
|
|
|
|
|
|
|
```text
|
2022-01-24 12:40:43 +03:00
|
|
|
> { a = { b = 1 } }
|
|
|
|
{ a = { b = 1 } }
|
2022-03-03 16:10:47 +03:00
|
|
|
|
2022-01-24 12:40:43 +03:00
|
|
|
> { a.b = 1 }
|
|
|
|
{ a = { b = 1 } }
|
|
|
|
|
|
|
|
> { a.b = 1, a.c = 2, b = 3}
|
|
|
|
{ a = { b = 1, c = 2 }, b = 3 }
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
When fields are enclosed with double quotes (`"`), you can use string
|
|
|
|
interpolation to create or access fields:
|
|
|
|
|
|
|
|
```text
|
2022-02-24 11:34:55 +03:00
|
|
|
> let k = "a" in { "%{k}" = 1 }
|
2022-01-27 16:41:13 +03:00
|
|
|
{ a = 1 }
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> let k = "a" in { a = 1 }."%{k}"
|
2022-01-27 16:41:13 +03:00
|
|
|
1
|
|
|
|
```
|
|
|
|
|
2022-01-25 15:26:47 +03:00
|
|
|
## Constructs
|
2022-01-14 16:56:39 +03:00
|
|
|
|
|
|
|
### If-Then-Else
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
This construct allows conditional branching in your code. You can use it as
|
|
|
|
`if <bool expr> then <expr> else <expr>`.
|
2022-01-18 12:09:04 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-18 12:09:04 +03:00
|
|
|
> if true then "TRUE :)" else "false :("
|
|
|
|
"TRUE :)"
|
|
|
|
|
|
|
|
> if false then "Not this one" else "This one"
|
|
|
|
"This one"
|
|
|
|
|
|
|
|
> if "forty-two" == 42 then "equal?" else "unequal"
|
|
|
|
"unequal"
|
2022-01-25 15:28:18 +03:00
|
|
|
|
|
|
|
> ["1"] @ (if 42 == "42" then ["3"] else ["2"]) @ ["3"]
|
|
|
|
["1", "2", "3"]
|
2022-01-18 12:09:04 +03:00
|
|
|
```
|
2022-01-14 16:56:39 +03:00
|
|
|
|
|
|
|
### Let-In
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
Let-in allows the binding of an expression. It is used as
|
|
|
|
`let <rec?> <ident> = <expr> in <expr>`. The `rec` keyword in Let-in constructs
|
|
|
|
allows the let binding to become recursive, enabling the use of the `<ident>`
|
|
|
|
within the first `<expr>`.
|
2022-01-18 12:09:04 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-18 12:09:04 +03:00
|
|
|
> let r = { a = "a", b = "b" } in r.a
|
|
|
|
"a"
|
|
|
|
|
|
|
|
> let inner = { inside = true } in let outer = { outside = inner.inside } in outer.outside
|
|
|
|
true
|
|
|
|
|
|
|
|
> let a = 1 in let b = 2 in a + b
|
|
|
|
3
|
2022-04-20 14:04:40 +03:00
|
|
|
|
|
|
|
> let rec f = fun n => if n == 0 then n else n + f (n - 1) in f 10
|
|
|
|
55
|
|
|
|
|
|
|
|
> let rec fib = fun n => if n <= 2 then 1 else fib (n - 1) + fib (n - 2) in fib 9
|
|
|
|
34
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
> let rec repeat = fun n x => if n <= 0 then [] else repeat (n - 1) x @ [x] in
|
|
|
|
repeat 3 "foo"
|
2022-04-20 14:04:40 +03:00
|
|
|
["foo", "foo", "foo"]
|
2022-01-18 12:09:04 +03:00
|
|
|
```
|
2022-01-14 16:56:39 +03:00
|
|
|
|
2022-01-18 12:09:04 +03:00
|
|
|
## Functions
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
A function is declared using the `fun` keyword, then arguments separated with
|
|
|
|
spaces, and finally an arrow `=>` to add the body of the function. To call a
|
|
|
|
function, just add the arguments after it separated with spaces. Functions in
|
|
|
|
Nickel are curried, meaning that a function taking multiple arguments is
|
|
|
|
actually a function that takes a single argument and returns a function taking
|
|
|
|
the rest of the arguments, until it is applied.
|
2022-01-18 12:09:04 +03:00
|
|
|
|
2022-01-25 16:47:43 +03:00
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-18 12:09:04 +03:00
|
|
|
> (fun a b => a + b) 1 2
|
|
|
|
3
|
|
|
|
|
|
|
|
let add = fun a b => a + b in add 1 2
|
|
|
|
3
|
|
|
|
|
|
|
|
> let add = fun a b => a + b in
|
|
|
|
let add1 = add 1 in
|
|
|
|
add1 2
|
|
|
|
3
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
All existing infix operators in Nickel can be turned into functions by putting
|
|
|
|
them inside parentheses.
|
2022-01-25 16:47:43 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-25 16:47:43 +03:00
|
|
|
> 1 + 2
|
|
|
|
3
|
|
|
|
|
|
|
|
> (+) 1 2
|
|
|
|
3
|
|
|
|
|
|
|
|
> let increment = fun n => (+) 1 n in
|
|
|
|
increment 41
|
|
|
|
42
|
|
|
|
|
|
|
|
> let increment = (+) 1 in
|
|
|
|
increment 41
|
|
|
|
42
|
|
|
|
|
2022-02-23 13:32:10 +03:00
|
|
|
> let flatten = array.fold (@) [] in flatten [[1, 2], [3], [4, 5]]
|
2022-01-25 16:47:43 +03:00
|
|
|
[ 1, 2, 3, 4, 5 ]
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Functions might be composed using the *pipe operator*. The pipe operator allows
|
|
|
|
for a function application `f x` to be written as `x |> f`. This operator is
|
|
|
|
left-associative, so `x |> f |> g` will be interpreted as `g (f x)`.
|
2022-01-25 16:47:43 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-02-23 13:32:10 +03:00
|
|
|
> "Hello World" |> string.split " "
|
2022-01-25 16:47:43 +03:00
|
|
|
["Hello", "World"]
|
|
|
|
|
2022-02-07 15:19:35 +03:00
|
|
|
> "Hello World"
|
2022-02-23 13:32:10 +03:00
|
|
|
|> string.split " "
|
2022-02-23 13:32:10 +03:00
|
|
|
|> array.head
|
2022-01-25 16:47:43 +03:00
|
|
|
"Hello"
|
|
|
|
|
2022-02-07 15:19:35 +03:00
|
|
|
> "Hello World"
|
2022-02-23 13:32:10 +03:00
|
|
|
|> string.split " "
|
2022-02-23 13:32:10 +03:00
|
|
|
|> array.head
|
2022-02-23 13:32:10 +03:00
|
|
|
|> string.uppercase
|
2022-01-25 16:47:43 +03:00
|
|
|
"HELLO"
|
|
|
|
```
|
|
|
|
|
2022-01-24 12:50:49 +03:00
|
|
|
## Typing
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
To give a type to a value, we write it with `< value > : < type >`. More
|
|
|
|
information on typing in the relevant document.
|
2022-01-24 12:50:49 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
2022-03-07 14:27:09 +03:00
|
|
|
```nickel
|
2022-01-24 12:50:49 +03:00
|
|
|
5 : Num
|
|
|
|
"Hello" : Str
|
|
|
|
|
|
|
|
(fun a b => a + b) : Num -> Num -> Num
|
|
|
|
let add : Num -> Num -> Num = fun a b => a + b
|
|
|
|
|
2022-02-23 13:32:10 +03:00
|
|
|
{a: Num = 1, b: Bool = true, c : Array Num = [ 1 ]}
|
|
|
|
let r : {a : Num, b : Bool, c : Array Num} = { a = 1, b = true, c = [ 1 ] }
|
2022-01-24 12:50:49 +03:00
|
|
|
|
|
|
|
{ a = 1, b = 2 } : { _ : Num }
|
|
|
|
let r : { _ : Num } = { a = 1, b = 2 }
|
|
|
|
```
|
2022-01-24 13:46:15 +03:00
|
|
|
|
|
|
|
## Metadata
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Metadata are used to attach contracts (more information in relevant
|
|
|
|
documentation), documentation or priority to values. A metadata is introduced
|
|
|
|
with the syntax `<value> | <metadata>`. Multiple metadata can be chained.
|
2022-01-24 13:46:15 +03:00
|
|
|
|
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-01-24 13:46:15 +03:00
|
|
|
> 5 | Num
|
|
|
|
5
|
|
|
|
|
|
|
|
> 5 | Bool
|
|
|
|
error: Blame error: contract broken by a value.
|
|
|
|
|
2022-02-23 13:32:10 +03:00
|
|
|
> let SmallNum = contract.from_predicate (fun x => x < 5) in
|
2022-02-23 12:28:23 +03:00
|
|
|
1 | SmallNum
|
2022-01-24 13:46:15 +03:00
|
|
|
1
|
|
|
|
|
2022-02-23 13:32:10 +03:00
|
|
|
> let SmallNum = contract.from_predicate (fun x => x < 5) in
|
2022-02-23 12:28:23 +03:00
|
|
|
10 | SmallNum
|
2022-01-24 13:46:15 +03:00
|
|
|
error: Blame error: contract broken by a value.
|
|
|
|
|
2022-02-23 13:32:10 +03:00
|
|
|
> let SmallNum = contract.from_predicate (fun x => x < 5) in
|
|
|
|
let NotTooSmallNum = contract.from_predicate (fun x => x >= 2) in
|
2022-02-07 15:19:35 +03:00
|
|
|
3 | Num
|
2022-02-23 12:28:23 +03:00
|
|
|
| SmallNum
|
|
|
|
| NotTooSmallNum
|
2022-01-24 13:46:15 +03:00
|
|
|
3
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Adding documentation can be done with `| doc < string >`. Examples:
|
|
|
|
|
|
|
|
```text
|
2022-01-24 13:46:15 +03:00
|
|
|
> 5 | doc "The number five"
|
|
|
|
5
|
|
|
|
|
2022-02-24 11:34:55 +03:00
|
|
|
> true | Bool | doc m%"
|
2022-01-24 13:46:15 +03:00
|
|
|
If something is true,
|
|
|
|
it is based on facts rather than being invented or imagined,
|
|
|
|
and is accurate and reliable.
|
|
|
|
(Collins dictionary)
|
2022-02-24 11:34:55 +03:00
|
|
|
"%m
|
2022-01-24 13:46:15 +03:00
|
|
|
true
|
|
|
|
```
|
|
|
|
|
2022-08-02 16:41:43 +03:00
|
|
|
Record contracts can set default values using the `default` metadata: It is
|
|
|
|
noted as `| default = < default value >`. This is especially useful when merging
|
|
|
|
records (more about this in the dedicated document about merge).
|
|
|
|
|
2022-01-24 13:46:15 +03:00
|
|
|
Examples:
|
2022-08-02 16:41:43 +03:00
|
|
|
|
|
|
|
```text
|
2022-02-07 15:19:35 +03:00
|
|
|
> let Ais2ByDefault = { a | default = 2 } in
|
2022-02-23 12:28:23 +03:00
|
|
|
{} | Ais2ByDefault
|
2022-01-24 13:46:15 +03:00
|
|
|
{ a = 2 }
|
|
|
|
|
2022-02-07 15:19:35 +03:00
|
|
|
> let Ais2ByDefault = { a | default = 2 } in
|
2022-02-23 12:28:23 +03:00
|
|
|
{ a = 1 } | Ais2ByDefault
|
2022-01-24 13:46:15 +03:00
|
|
|
{ a = 1 }
|
2022-01-27 16:45:01 +03:00
|
|
|
|
|
|
|
> { foo | default = 1, bar = foo + 1 }
|
|
|
|
{ foo = 1, bar = 2 }
|
|
|
|
|
2022-02-07 15:19:35 +03:00
|
|
|
> {foo | default = 1, bar = foo + 1} & {foo = 2}
|
2022-01-27 16:45:01 +03:00
|
|
|
{ foo = 2, bar = 3 }
|
2022-01-24 13:46:15 +03:00
|
|
|
```
|