Commit 7878d8ac authored by matu3ba's avatar matu3ba
Browse files

fix(manual,tests): test chapter variables up to arithmetic

rephrase wording, merge tests of same functionality
parent 1f2d8e25
# Variables
The `let` builtin is used to create local variables within the shell, and apply basic arithmetic
to variables. The `export` keyword may be used to do the same for the creation of external
variables. Variables cannot be created the POSIX way, as the POSIX way is awkard to read/write
and parse.
```sh
let string_variable = "hello string"
let array_variable = [ hello array ]
{{#include ../../../tests/variables.ion:variables}}
```
```txt
{{#include ../../../tests/variables.out:6:7}}
```
## Multiple Assignments
Ion also supports setting multiple values at the same time
```sh
let a b = one two
echo $a
echo $b
let a b = one [two three four]
echo $a
echo @b
{{#include ../../../tests/variables.ion:multiple_assignment}}
```
```txt
one
two
one
two three four
{{#include ../../../tests/variables.out:9:12}}
```
## Type-Checked Assignments
It's also possible to designate the type that a variable is allowed to be initialized with.
Boolean type assignments will also normalize inputs into either `true` or `false`. When an
invalid value is supplied, the assignment operation will fail and an error message will be
printed. All assignments after the failed assignment will be ignored.
```sh
let a:bool = 1
let b:bool = true
let c:bool = n
echo $a $b $c
let a:str b:[str] c:int d:[float] = one [two three] 4 [5.1 6.2 7.3]
echo $a
echo @b
echo $c
echo @d
{{#include ../../../tests/variables.ion:type_checked_assignment}}
```
```
true
true
false
one
two three
4
5.1 6.2 7.3
```txt
{{#include ../../../tests/variables.out:14:19}}
```
## Dropping Variables
......@@ -64,12 +36,8 @@ two three
Variables may be dropped from a scope with the `drop` keyword. Considering that a variable
can only be assigned to one type at a time, this will drop whichever value is assigned to
that type.
```
let string = "hello"
drop string
let array = [ hello world ]
drop array
```sh
{{#include ../../../tests/variables.ion:dropping_variables}}
```
## Supported Primitive Types
......
# String Variables
Using the `let` builtin, a string can easily be created by specifying the name, and an expression
that will be evaluated before assigning it to that variable.
We can evaluate expressions to assign their result to the variable and print with with **$** sigil.
Read the chapter expansions for more information about the expansion behavior.
```sh
let git_branch = $(git rev-parse --abbrev-ref HEAD ^> /dev/null)
{{#include ../../../tests/string_vars.ion:string_variables}}
```
## Calling a string variable.
To call a string variable, you may utilize the **$** sigil along with the name of the variable. For more information on expansions, see the expansions section of this manual.
```sh
echo $git_branch
```txt
{{#include ../../../tests/string_vars.out:string_variables}}
```
## Slicing a string.
Strings can be sliced in Ion using a range.
```sh
let foo = "Hello, World"
echo $foo[..5]
echo $foo[7..]
echo $foo[2..9]
{{#include ../../../tests/string_vars.ion:string_slicing}}
```
```txt
{{#include ../../../tests/string_vars.out:string_slicing}}
```
## String concatenation
The `++=` and `::=` operators can be used to efficiently concatenate a string in-place.
```sh
let string = "ello"
let string ::= H
let string ++= ", world!"
echo $string
```
{{#include ../../../tests/string_vars.ion:string_concatenation}}
```
Hello, world!
```txt
{{#include ../../../tests/string_vars.out:string_concatenation}}
```
# Array Variables
The **[]** syntax in Ion is utilized to denote that the contents within should be parsed as an
array expression. Array variables are also created using the same `let` keyword, but `let` makes
the distinction between a string and an array by additionally requiring that all array arguments
are wrapped within the **[]** syntax. If an array is supplied to `let` that is not explicitly
declared as an array, then it will be coerced into a space-separated string. This design decision
was made due to the possibility of an expanded array with one element being interpreted as a
string.
The **[]** syntax in Ion denotes that the contents within should be parsed as an
array expression.
On using `let` keyword for array variables, all array arguments must be wrapped within the **[]** syntax. Otherwise it will be coerced into a space-separated string.
This design decision was made due to the possibility of an expanded array with one element
being interpreted as a string.
Once created, you may call an array variable in the same manner as a string variable, but you
must use the **@** sigil instead of **$**. When expanded, arrays will be expanded into multiple
arguments, so it is possible to use arrays to set multiple arguments in commands. Do note, however,
that if an array is double quoted, it will be coerced into a string, which is a behavior that
is equivalent to invoking the `$join(array)` method.
arguments. Hence it is possible to use arrays to set multiple arguments in commands.
**NOTE** If an array is double quoted, it will be coerced into a string. This behavior is equivalent to invoking the `$join(array)` method.
**NOTE**: Brace expansions also create arrays.
## Create a new array
Arguments enclosed within brackets are treated as elements within an array.
```sh
let array = [ one two 'three four' ]
{{#include ../../../tests/array_vars.ion:create_array}}
```
```txt
```
## Indexing into an array
Values can be fetched from an array via their position in the array as the index.
```sh
let array = [ 1 2 3 4 5 6 7 8 9 10 ]
echo @array[0]
echo @array[5..=8]
{{#include ../../../tests/array_vars.ion:index_array}}
```
```txt
{{#include ../../../tests/array_vars.out:index_array}}
```
## Copy array into a new array
Passing an array within brackets enables performing a deep copy of that array.
```sh
let array_copy = [ @array ]
{{#include ../../../tests/array_vars.ion:array_copy}}
```
```txt
{{#include ../../../tests/array_vars.out:array_copy}}
```
## Array join
This will join each element of the array into a string, adding spaces between each element.
```sh
let array = [ hello world ]
let other_array = [ this is the ion ]
let array = [ @array @other_array shell ]
let as_string = @array
echo @array
echo $as_string
{{#include ../../../tests/array_vars.ion:array_join}}
```
```txt
hello world this is the ion shell
hello world this is the ion shell
{{#include ../../../tests/array_vars.out:array_join}}
```
## Array concatenation
## Array concatenation and variable stripping
The `++=` and `::=` operators can be used to efficiently concatenate an array in-place.
```sh
let array = [1 2 3]
let array ++= [5 6 7]
let array ::= 0
echo @array
{{#include ../../../tests/array_vars.ion:array_concat_var_strip}}
```
```txt
0 1 2 3 5 6 7
{{#include ../../../tests/array_vars.out:array_concat_var_strip}}
```
## Expand array as arguments to a command
Arrays are useful to pass as arguments to a command. Each element will be expanded as an
individual argument, if any arguments exist.
```sh
let args = [-l -a --color]
ls @args
```
## Using command output as array
## Practical array usage
Passing arrays as command arguments and capturing output of commands as arrays is useful.
```sh
mkdir -p _tmp _tmp/t1 _tmp/t2
cd _tmp
let res = [ @(ls) ]
echo @res # output the array
cd ..
rm -fr _tmp
{{#include ../../../tests/array_vars.ion:practical_array}}
```
```txt
t1 t2
{{#include ../../../tests/array_vars.out:practical_array}}
```
# Maps
Maps, (AKA dictionaries), provide key-value data association. Ion has two variants of maps: BTree and Hash. Hash maps are fast but store data in a random order; whereas BTree maps are slower but keep their data in a sorted order. If not sure what to use, it's best to go with Hash maps.
Maps, (AKA dictionaries), provide key-value data association. Ion has two variants of maps: Hash and BTree. Hash maps are fast but store data in a random order. BTree maps are slower, but keep their data in a sorted order. If not sure what to use, go with Hash maps.
Creating maps uses the same right-hand-side array syntax. However for design simplicity, users must annotate the type to translate the array into a map.
Please note, the map's inner type specifies the value's type and not of the key. Keys will always be typed `str`.
## Create a HashMap
```
let hashmap:hmap[str] = [ foo=hello bar=world fizz=I buzz=was bazz=here ]
```
## Create a BTreeMap
```
let btreemap:bmap[str] = [ foo=hello bar=world fizz=I buzz=was bazz=here ]
```
## Fetch a variable by key
```
let x = bazz
echo @hashmap[bar] @hashmap[$x]
```
## Insert a new key
## HashMap
```sh
{{#include ../../../tests/map_vars.ion:hashmap}}
```
let x[bork] = oops
```txt
{{#include ../../../tests/map_vars.out:hashmap}}
```
## Iterate keys in the map
```
echo @keys(hashmap)
```
## Iterate values in the map
```
echo @values(hashmap)
```
## Iterate key/value pairs in the map
```
echo @hashmap
```
## Iterate key/value pairs in a loop
## BTreeMap
```sh
{{#include ../../../tests/map_vars.ion:btreemap}}
```
for key value in @hashmap
echo $key: $value
end
```txt
{{#include ../../../tests/map_vars.out:btreemap}}
```
......@@ -13,35 +13,21 @@ Operators currently supported are:
- [x] Powers (**\*\***)
## Individual Assignments
The following examples are a demonstration of applying a mathematical operation to an individual
variable -- first assigning `0` to the variable, then applying arithmetic operations to it.
variable.
```sh
let value = 0
let value += 5
let value -= 2
let value *= 3
let value //= 2
let value **= 10
let value /= 2
{{#include ../../../tests/arithmetic_vars.ion:individual_assignments}}
```
```txt
{{#include ../../../tests/arithmetic_vars.out:individual_assignments}}
```
## Multiple Assignments
It's also possible to perform a mathematical operation to multiple variables. Each variable will be
designated with a paired value.
```sh
let a b = 5 5
let a b += 3 2
let a b -= 1 1
echo $a $b
```
This will output the following:
{{#include ../../../tests/arithmetic_vars.ion:multiple_assignments}}
```
7 6
```txt
{{#include ../../../tests/arithmetic_vars.out:multiple_assignments}}
```
echo '# ANCHOR: individual_assignments'
let value = 5
echo $value
let value += 5
echo $value
let value -= 2
echo $value
let value *= 2
echo $value
let value //= 2
echo $value
let value **= 2
echo $value
let value /= 2
echo $value
echo '# ANCHOR_END: individual_assignments'
echo '# ANCHOR: multiple_assignments'
let a b = 5 5
echo $a $b
let a b += 5 5
echo $a $b
let a b -= 2 2
echo $a $b
let a b *= 2 2
echo $a $b
let a b //= 2 2
echo $a $b
let a b **= 2 2
echo $a $b
let a b /= 2 2
echo $a $b
echo '# ANCHOR_END: multiple_assignments'
# ANCHOR: individual_assignments
5
10
8
16
8
64.0
32.0
# ANCHOR_END: individual_assignments
# ANCHOR: multiple_assignments
5 5
10 10
8 8
16 16
8 8
64.0 64.0
32.0 32.0
# ANCHOR_END: multiple_assignments
let array = [1 2 3]
let array[0] = 4
echo @array
let value = 1
let array[$value] = 5
echo @array
let array[2]:int = 6
echo @array
let array = [ 4 4 5 5 5 6 6 6 6 ]
echo @array
let array ++= [ 1 2 3 ]
echo @array
let array ::= [ 1 2 3 ]
echo @array
let array \\= [ 4 5 6 ]
echo @array
let array = [ 1 2 2 3 3 3 ]
echo @array
let array ++= 4
echo @array
let array ::= 0
echo @array
let array \\= 3
echo @array
4 4 5 5 5 6 6 6 6
4 4 5 5 5 6 6 6 6 1 2 3
1 2 3 4 4 5 5 5 6 6 6 6 1 2 3
1 2 3 1 2 3
1 2 2 3 3 3
1 2 2 3 3 3 4
0 1 2 2 3 3 3 4
0 1 2 2 4
# Standard Arrays
echo '# ANCHOR: standardArrays'
let array = []
echo @array
let array = [1]
for i in @array
echo $i
end
let array = [1 [2 3] 4 [5 6]]
for i in @array
echo $i
end
for i in [1 [2 3] 4 [5 6]]
echo $i
end
# Array Command Substitution
echo '# ANCHOR_END: standardArrays'
echo '# ANCHOR: command_substitution'
let array_process = [ @(echo a b c d e) ]
for i in @array_process
echo $i
end
for i in @(echo a b c d e)
echo $i
end
# Array Concatenation
echo '# ANCHOR_END: command_substitution'
echo '# ANCHOR: concatenation'
let new_array = [@array @array_process]
for i in @new_array
echo $i
end
# As Command Arguments
echo '# ANCHOR_END: concatenation'
echo '# ANCHOR: array_as_command_args'
echo @array
echo @array_process
echo @new_array
# Slice by ID
echo '# ANCHOR_END: array_as_command_args'
echo '# ANCHOR: slice_by_id'
let array = [ 1 2 3 ]
echo @array[0]
echo @array[1]
echo @array[2]
echo [ 1 2 3 ][0]
echo [ 1 2 3 ][1]
echo [ 1 2 3 ][2]
echo @(echo 1 2 3)[0]
echo @(echo 1 2 3)[1]
echo @(echo 1 2 3)[2]
# Slice by Range
echo '# ANCHOR_END: slice_by_id'
echo '# ANCHOR: slice_by_range'
let array = [ 1 2 3 4 5 ]
echo @array[0..1]
echo @array[0...1]
echo @array[..3]
echo @array[3..]
echo @array[..]
# Slice Syntax w/ variables
echo '# ANCHOR_END: slice_by_range'
echo '# ANCHOR: slice_with_vars'
for index in 0..3
echo $(echo 😉😉😉)[$index]
end
# Convert Array to String
echo '# ANCHOR_END: slice_with_vars'
echo '# ANCHOR: convert_to_string'
let array = [ 1 2 3 4 5 ]
let as_string = @array
echo $as_string
let array = [1 2 3 4 5 6 7 8 9 10]
echo @array[0 1 7..]
echo @array[2 3 5..]
echo @array[5.. 3 2]
echo @array[5..8 1..3 9 2]
echo '# ANCHOR_END: convert_to_string'
# ANCHOR: standardArrays
1
1
......@@ -12,6 +13,8 @@
4
5
6
# ANCHOR_END: standardArrays
# ANCHOR: command_substitution
a
b
c
......@@ -22,6 +25,8 @@ b
c
d
e
# ANCHOR_END: command_substitution
# ANCHOR: concatenation
1
2
3
......@@ -33,9 +38,13 @@ b
c
d
e
# ANCHOR_END: concatenation
# ANCHOR: array_as_command_args
1 2 3 4 5 6
a b c d e
1 2 3 4 5 6 a b c d e
# ANCHOR_END: array_as_command_args
# ANCHOR: slice_by_id
1
2
3
......@@ -45,16 +54,23 @@ a b c d e
1
2
3
# ANCHOR_END: slice_by_id
# ANCHOR: slice_by_range
1
1 2
1 2 3
4 5
1 2 3 4 5
# ANCHOR_END: slice_by_range
# ANCHOR: slice_with_vars
😉
😉
😉
# ANCHOR_END: slice_with_vars
# ANCHOR: convert_to_string
1 2 3 4 5
1 2 8 9 10
3 4 6 7 8 9 10
6 7 8 9 10 4 3
6 7 8 2 3 10 3
# ANCHOR_END: convert_to_string
echo '# ANCHOR: array_assignments'
let array = [1 2 3]
let array[0] = 4
echo @array
let value = 1
let array[$value] = 5
echo @array
let array[2]:int = 6
echo @array
echo '# ANCHOR_END: array_assignments'