## In A Nutshell

This section is inspired by Learn X in Y minutes and its goal is to present the most basic features of Arturo, in a concise way, so that you can get started fast.

So... With X = Arturo and Y = ~15 minutes, here you are:

``````; 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
]

; colors - right, you can directly define them as well!
g1: #red
g2: #0077BF

; dates
h: now              ; 2021-05-03T17:10:48+02:00

; logical values
i1: true
i2: false
i3: maybe

;---------------------------------
; 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
; note it's 'if?' not 'if'
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 
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\[x]               ; two

; setting an array element
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...
``````