diff --git a/arturo.html.markdown b/arturo.html.markdown new file mode 100644 index 00000000..c3c4dc43 --- /dev/null +++ b/arturo.html.markdown @@ -0,0 +1,432 @@ +--- +language: arturo +filename: learnarturo.art +contributors: + - ["Dr.Kameleon", "https://github.com/drkameleon"] +--- + +```red +; 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... +``` + +## Additional resources + +- [Official documentation](https://arturo-lang.io/documentation/) - Arturo official documentation & reference. +- [Online playground](https://arturo-lang.io/playground/) - Online REPL for the Arturo programming language.