From ad6b3df619a464c99439534f436a85707b679c80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Yanis=20Zafir=C3=B3pulos?=
 <1265028+drkameleon@users.noreply.github.com>
Date: Thu, 14 Dec 2023 16:12:25 +0100
Subject: Add Arturo (#4161)

---
 arturo.html.markdown | 432 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 432 insertions(+)
 create mode 100644 arturo.html.markdown

(limited to 'arturo.html.markdown')

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.
-- 
cgit v1.2.3