; this is a comment ; this is another comment ;--------------------------------- ; VARIABLES & VALUES ;--------------------------------- ; numbers a1: 2 a2: 3.14 a3: to :complex [1 2.0] ; 1.0+2.0i ; strings c1: "this is a string" c2: { this is a multiline string that is indentation-agnostic } c3: {: this is a verbatim multiline string which will remain exactly as the original :} ; characters ch: `c` ; blocks/arrays d: [1 2 3] ; dictionaries e: #[ name: "John" surname: "Doe" age: 34 likes: [pizza spaghetti] ] ; yes, functions are values too f: function [x][ 2 * x ] ; dates g: now ; 2021-05-03T17:10:48+02:00 ; booleans h1: true h2: false ;--------------------------------- ; BASIC OPERATORS ;--------------------------------- ; simple arithmetic 1 + 1 ; => 2 8 - 1 ; => 7 4.2 - 1.1 ; => 3.1 10 * 2 ; => 20 35 / 4 ; => 8 35 // 4 ; => 8.75 2 ^ 5 ; => 32 5 % 3 ; => 2 ; bitwise operators and 3 5 ; => 1 or 3 5 ; => 7 xor 3 5 ; => 6 ; pre-defined constants pi ; => 3.141592653589793 epsilon ; => 2.718281828459045 null ; => null true ; => true false ; => false ;--------------------------------- ; COMPARISON OPERATORS ;--------------------------------- ; equality 1 = 1 ; => true 2 = 1 ; => false ; inequality 1 <> 1 ; => false 2 <> 1 ; => true ; more comparisons 1 < 10 ; => true 1 =< 10 ; => true 10 =< 10 ; => true 1 > 10 ; => false 1 >= 10 ; => false 11 >= 10 ; => true ;--------------------------------- ; CONDITIONALS ;--------------------------------- ; logical operators and? true true ; => true and? true false ; => false or? true false ; => true or? false false ; => false and? [1=2][2<3] ; => false ; (the second block will not be evaluated) ; simple if statements if 2 > 1 [ print "yes!"] ; yes! if 3 <> 2 -> print "true!" ; true! ; if/else statements if? 2 > 3 -> print "2 is greater than 3" else -> print "2 is not greater than 3" ; 2 is not greater than 3 ; switch statements switch 2 > 3 -> print "2 is greater than 3" -> print "2 is not greater than 3" ; 2 is not greater than 3 a: (2 > 3)["yes"]["no"] ; a: "no" a: (2 > 3)? -> "yes" -> "no" ; a: "no" (exactly the same as above) ; case/when statements case [1] when? [>2] -> print "1 is greater than 2. what?!" when? [<0] -> print "1 is less than 0. nope..." else -> print "here we are!" ; here we are! ;--------------------------------- ; LOOPS ;--------------------------------- ; with `loop` arr: [1 4 5 3] loop arr 'x [ print ["x =" x] ] ; x = 1 ; x = 4 ; x = 5 ; x = 3 ; with loop and custom index loop.with:'i arr 'x [ print ["item at position" i "=>" x] ] ; item at position 0 => 1 ; item at position 1 => 4 ; item at position 2 => 5 ; item at position 3 => 3 ; using ranges loop 1..3 'x -> ; since it's a single statement print x ; there's no need for [block] notation ; we can wrap it up using the `->` syntactic sugar loop `a`..`c` 'ch -> print ch ; a ; b ; c ; picking multiple items loop 1..10 [x y] -> print ["x =" x ", y =" y] ; x = 1 , y = 2 ; x = 3 , y = 4 ; x = 5 , y = 6 ; x = 7 , y = 8 ; x = 9 , y = 10 ; looping through a dictionary dict: #[name: "John", surname: "Doe", age: 34] loop dict [key value][ print [key "->" value] ] ; name -> John ; surname -> Doe ; age -> 34 ; while loops i: new 0 while [i<3][ print ["i =" i] inc 'i ] ; i = 0 ; i = 1 ; i = 2 ;--------------------------------- ; STRINGS ;--------------------------------- ; case a: "tHis Is a stRinG" print upper a ; THIS IS A STRING print lower a ; this is a string print capitalize a ; tHis Is a stRinG ; concatenation a: "Hello " ++ "World!" ; a: "Hello World!" ; strings as an array split "hello" ; => [h e l l o] split.words "hello world" ; => [hello world] print first "hello" ; h print last "hello" ; o ; conversion to :string 123 ; => "123" to :integer "123" ; => 123 ; joining strings together join ["hello" "world"] ; => "helloworld" join.with:"-" ["hello" "world"] ; => "hello-world" ; string interpolation x: 2 print ~"x = |x|" ; x = 2 ; interpolation with `print` print ["x =" x] ; x = 2 ; (`print` works by calculating the given block ; and joining the different values as strings ; with a single space between them) ; templates print render.template { <||= switch x=2 [ ||> Yes, x = 2 <||][||> No, x is not 2 <||]||> } ; Yes, x = 2 ; matching prefix? "hello" "he" ; => true suffix? "hello" "he" ; => false contains? "hello" "ll" ; => true contains? "hello" "he" ; => true contains? "hello" "x" ; => false in? "ll" "hello" ; => true in? "x" "hello" ; => false ;--------------------------------- ; BLOCKS ;--------------------------------- ; calculate a block arr: [1 1+1 1+1+1] @arr ; => [1 2 3] ; execute a block sth: [print "Hello world"] ; this is perfectly valid, ; could contain *anything* ; and will not be executed... do sth ; Hello world ; (...until we tell it to) ; array indexing arr: ["zero" "one" "two" "three"] print first arr ; zero print arr\0 ; zero print last arr ; three print arr\3 ; three x: 2 print get arr x ; two print arr \ 2 ; two ; (using the `\` infix alias for get - ; notice space between the operands! ; otherwise, it'll be parsed as a path) ; setting an array element arr\0: "nada" set arr 2 "dos" print arr ; nada one dos three ; adding elements to an array arr: new [] 'arr ++ "one" 'arr ++ "two" print arr ; one two ; remove elements from an array arr: new ["one" "two" "three" "four"] 'arr -- "two" ; arr: ["one" "three" "four"] remove 'arr .index 0 ; arr: ["three" "four"] ; getting the size of an array arr: ["one" 2 "three" 4] print size arr ; 4 ; getting a slice of an array print slice ["one" "two" "three" "four"] 0 1 ; one two ; check if array contains a specific element print contains? arr "one" ; true print contains? arr "five" ; false ; sorting array arr: [1 5 3 2 4] sort arr ; => [1 2 3 4 5] sort.descending arr ; => [5 4 3 2 1] ; mapping values map 1..10 [x][2*x] ; => [2 4 6 8 10 12 14 16 18 20] map 1..10 'x -> 2*x ; same as above map 1..10 => [2*&] ; same as above map 1..10 => [2*] ; same as above ; selecting/filtering array values select 1..10 [x][odd? x] ; => [1 3 5 7 9] select 1..10 => odd? ; same as above filter 1..10 => odd? ; => [2 4 6 8 10] ; (now, we leave out all odd numbers - ; while select keeps them) ; misc operations arr: ["one" 2 "three" 4] reverse arr ; => [4 "three" 2 "one"] shuffle arr ; => [2 4 "three" "one"] unique [1 2 3 2 3 1] ; => [1 2 3] permutate [1 2 3] ; => [[1 2 3] [1 3 2] [3 1 2] [2 1 3] [2 3 1] [3 2 1]] take 1..10 3 ; => [1 2 3] repeat [1 2] 3 ; => [1 2 1 2 1 2] ;--------------------------------- ; FUNCTIONS ;--------------------------------- ; declaring a function f: function [x][ 2*x ] f: function [x]-> 2*x ; same as above f: $[x]->2*x ; same as above (only using the `$` alias ; for the `function`... function) ; calling a function f 10 ; => 20 ; returning a value g: function [x][ if x < 2 -> return 0 res: 0 loop 0..x 'z [ res: res + z ] return res ] ;--------------------------------- ; CUSTOM TYPES ;--------------------------------- ; defining a custom type define :person [ ; define a new custom type "Person" name ; with fields: name, surname, age surname age ][ ; with custom post-construction initializer init: [ this\name: capitalize this\name ] ; custom print function print: [ render "NAME: |this\name|, SURNAME: |this\surname|, AGE: |this\age|" ] ; custom comparison operator compare: 'age ] ; create a method for our custom type sayHello: function [this][ ensure -> is? :person this print ["Hello" this\name] ] ; create new objects of our custom type a: to :person ["John" "Doe" 34] ; let's create 2 "Person"s b: to :person ["jane" "Doe" 33] ; and another one ; call pseudo-inner method sayHello a ; Hello John sayHello b ; Hello Jane ; access object fields print ["The first person's name is:" a\name] ; The first person's name is: John print ["The second person's name is:" b\name] ; The second person's name is: Jane ; changing object fields a\name: "Bob" sayHello a ; Hello Bob ; verifying object type print type a ; :person print is? :person a ; true ; printing objects print a ; NAME: John, SURNAME: Doe, AGE: 34 ; sorting user objects (using custom comparator) sort @[a b] ; Jane..., John... sort.descending @[a b] ; John..., Jane...