├── README.md
└── images
├── atom-naming.png
├── module-naming.png
└── variable-naming.png
/README.md:
--------------------------------------------------------------------------------
1 | # Elixir Quick Reference
2 | A quick reference for the Elixir programming Language and standard library.
3 |
4 | Elixir Website: http://elixir-lang.org/
5 | Elixir Documentation: http://elixir-lang.org/docs.html
6 | Elixir Source: https://github.com/elixir-lang/elixir
7 | Try Elixir Online: https://glot.io/new/elixir
8 | Elixir Regex editor/testor: http://www.elixre.uk/
9 | This Document: https://github.com/itsgreggreg/elixir_quick_reference
10 |
11 |
12 |
13 | # Table of Contents
14 |
15 | - [Basic Types](#basic-types)
16 | - [Integer](#integer)
17 | - [Float](#float)
18 | - [Atom](#atom)
19 | - [Boolean](#boolean)
20 | - [Nil](#nil)
21 | - [Binary](#binary)
22 | - [String](#string)
23 | - [Escape Sequences](#escape-sequences)
24 | - [Regular Expression](#regular-expression)
25 | - [Collection Types](#collection-types)
26 | - [List](#list)
27 | - [Charlist](#charlist)
28 | - [Tuple](#tuple)
29 | - [Keyword List](#keyword-list)
30 | - [Map](#map)
31 | - [Struct](#struct)
32 | - [Range](#range)
33 | - [Streams](#streams)
34 | - [Syntax](#syntax)
35 | - [Variables](#variables)
36 | - [Operators](#operators)
37 | - [Standard infix](#standard-infix)
38 | - [Standard prefix](#standard-prefix)
39 | - [= (match)](#-match)
40 | - [^ (pin)](#-pin)
41 | - [|> (pipe)](#-pipe)
42 | - [=~ (string match)](#-string-match)
43 | - [? (codepoint)](#-codepoint)
44 | - [& (capture)](#-capture)
45 | - [Ternary](#ternary)
46 | - [in](#in)
47 | - [Comments](#comments)
48 | - [Semicolons](#semicolons)
49 | - [Do, End](#do-end)
50 | - [Pattern Matching](#pattern-matching)
51 | - [Binaries](#binaries)
52 | - [Reserved Words](#reserved-words)
53 | - [Truthiness](#truthiness)
54 | - [Sorting](#sorting)
55 | - [Modules](#modules)
56 | - [Declaration](#declaration)
57 | - [Module Functions](#module-functions)
58 | - [Private Functions](#private-functions)
59 | - [Working with other modules](#working-with-other-modules)
60 | - [Attributes](#attributes)
61 | - [Documentation](#documentation)
62 | - [Introspection](#introspection)
63 | - [Errors](#errors)
64 | - [Raise](#raise)
65 | - [Custom Error](#custom-error)
66 | - [Rescue](#rescue)
67 | - [Control Flow](#control-flow)
68 | - [if/unless](#ifunless)
69 | - [case](#case)
70 | - [cond](#cond)
71 | - [throw/catch](#throwcatch)
72 | - [with](#with)
73 | - [Guards](#guards)
74 | - [Anonymous Functions](#anonymous-functions)
75 | - [Comprehensions](#comprehensions)
76 | - [Sigils](#sigils)
77 | - [Metaprogramming](#metaprogramming)
78 | - [Processes](#processes)
79 | - [Structs](#structs)
80 | - [Working with Files](#working-with-files)
81 | - [Erlang Interoperability](#erlang-interoperability)
82 | - [IEx](#iex)
83 | - [Mix](#mix)
84 | - [Applications](#applications)
85 | - [Tasks](#tasks)
86 | - [Tests](#tests)
87 | - [Style Guide](#style-guide)
88 |
89 |
90 |
91 |
92 | ## Basic Types
93 |
94 | ### Integer
95 | Can be specified in base 10, hex, or binary. All are stored as base 10.
96 |
97 | ```elixir
98 | > 1234567 == 1_234_567 # true
99 | > 0xcafe == 0xCAFE # true
100 | > 0b10101 == 65793 # true
101 | > 0xCafe == 0b1100101011111110 # true
102 | > 0xCafe == 51_966 # true
103 | > Integer.to_string(51_966, 16) == "CAFE" # true
104 | > Integer.to_string(0xcafe) == "51996" # true
105 | ```
106 |
107 | ### Float
108 | 64bit double precision. Can be specified with an exponent. Cannot begin or end with `.`.
109 |
110 | ```elixir
111 | > 1.2345
112 | > 0.001 == 1.0e-3 # true
113 | > .001 # syntax error!
114 | ```
115 |
116 | ### Atom
117 | Constants whose name is their value.
118 | Are named in this format:
119 |
120 | 
121 | To use other characters you must quote the atom.
122 | TODO: Note which characters can be used when quoted.
123 | Stored in a global table once used and never de-allocated so avoid programmatic creation.
124 |
125 | ```elixir
126 | > :something
127 | > :_some_thing
128 | > :allowed?
129 | > :Some@Thing@12345
130 | > :"Üñîçødé and Spaces"
131 | > Atom.to_string(:Yay!) # "Yay!"
132 | > :123 # syntax error!
133 | ```
134 |
135 | ### Boolean
136 | `true` and `false` are just syntactic sugar for `:true` and `:false` and not a special type.
137 |
138 | ```elixir
139 | > true == :true # true
140 | > false == :false # true
141 | > is_boolean(:true) # true
142 | > is_atom(false) # true
143 | > is_boolean(:True) # false!
144 | ```
145 |
146 | ### Nil
147 | `nil` is syntactic sugar for `:nil` and is not a special type.
148 |
149 | ```elixir
150 | > nil == :nil # true
151 | > is_atom(nil) # true
152 | ```
153 |
154 | ### Binary
155 | A binary is a sequence of bytes enclosed in `<< >>` and separated with `,`.
156 | By default each number is 8 bits though size can be specified with:
157 | `::size(n)`, `::n`, `::utf8`, `::utf16`, `::utf32` or `::float`
158 | If the number of bits in a binary is not divisible by 8, it is considered a bitstring.
159 | Binaries are concatenated with `<>`.
160 | ```elixir
161 | > <<0,1,2,3>>
162 | > <<100>> == <<100::size(8)>> # true
163 | > <<4::float>> == <<64, 16, 0, 0, 0, 0, 0, 0>> # true
164 | > <<65::utf32>> == <<0, 0, 0, 65>> # true
165 | > <<0::2, 1::2>> == <<1::4>> # true
166 | > <<1,2>> <> <<3,4>> == <<1,2,3,4>> # true
167 | > is_binary(<<1,2,3,4>>) # true
168 | > is_binary(<<1::size(4)>>) # false!, num of bits not devisible by 8
169 | > is_bitstring(<<1::size(4)>>) # true
170 | ```
171 |
172 | ### String
173 | Strings are UTF-8 encoded binaries. They are enclosed in double quotes(`"`).
174 | They can span multiple lines and contain interpolations.
175 | Interpolations are enclosed in `#{}` and can contain any expression.
176 | Strings, being binaries, are concatenated with `<>`.
177 |
178 | ```elixir
179 | > "This is a string."
180 | > "☀★☂☻♞☯☭☢€→☎♫♎⇧☮♻⌘⌛☘☊♔♕♖☦♠♣♥♦♂♀" # no problem :)
181 | > "This is an #{ Atom.to_string(:interpolated) } string."
182 | > "Where is " <> "my other half?"
183 | > "multi\nline" == "multi
184 | line" # true
185 | > <<69,108,105,120,105,114>> == "Elixir" # true
186 | > String.length("🎩") # 1
187 | > byte_size("🎩") # 4
188 | > is_binary("any string") # true
189 | > String.valid?("こんにちは") # true
190 | > String.valid?("hello" <> <<255>>) # false!
191 | > String.valid?(<<4>>) # true
192 | > String.printable?(<<4>>) # false! 4 is a valid UTF-8 codepoint, but is not printable.
193 | ```
194 | #### Escape Sequences
195 | characters | whitespace | control sequences
196 | --------------------------|---------------------|----------------------
197 | `\"` – double quote | `\b` – backspace | `\a` – bell/alert
198 | `\'` – single quote | `\f` - form feed | `\d` - delete
199 | `\\` – single backslash | `\n` – newline | `\e` - escape
200 | | `\s` – space | `\r` – carriage return
201 | | `\t` - tab | `\0` - null byte
202 | | `\v` – vertical tab |
203 |
204 | `\x...` - character with hexadecimal representation.
205 | `\x{...}` - character with hexadecimal representation with one or more hexadecimal digits.
206 | ```elixir
207 | > "\x3f" == "?" # true
208 | > "\x{266B}" == "♫" # true
209 | > "\x{2660}" == "♠" # true
210 | ```
211 |
212 |
213 |
214 | ### Regular Expression
215 | Inherited from Erlang's `re` module and are Perl compatible.
216 | Written literally with the `~r` [Sigil](#sigils) and can span multiple lines.
217 | Can have a number of modifiers specified directly after the pattern.
218 | Many functions take a captures option that limits captures.
219 |
220 | **Modifiers**:
221 | - `u` enables unicode specific patterns like \p and changes escapes like \w, \W, \s and friends to also match on unicode. It expects valid unicode strings to be given on match
222 | - `i` ignore case
223 | - `s` dot matches newlines and also set newline to anycrlf.
224 | - `m` ^ and $ match the start and end of each line; use \A and \z to match the end or start of the string
225 | - `x` whitespace characters are ignored except when escaped and `#` delimits comments
226 | - `f` forces the unanchored pattern to match before or at the first newline, though the matched text may continue over the newline
227 | r - inverts the “greediness” of the regexp
228 |
229 | **To override newline treatment start the pattern with**:
230 | - `(*CR)` carriage return
231 | - `(*LF)` line feed
232 | - `(*CRLF)` carriage return, followed by linefeed
233 | - `(*ANYCRLF)` any of the three above
234 | - `(*ANY)` all Unicode newline sequences
235 |
236 | ```elixir
237 | > Regex.compile!("caf[eé]") == ~r/caf[eé]/ # true
238 | > Regex.match?(~r/caf[eé]/, "café") # true
239 | > Regex.regex?(~r"caf[eé]") # true
240 | > Regex.regex?("caf[eé]") # false! string not compiled regex
241 | > Regex.run(~r/hat: (.*)/, "hat: 🎩", [capture: :all_but_first]) == ["🎩"] # true
242 | # Modifiers
243 | > Regex.match?(~r/mr. bojangles/i, "Mr. Bojangles") # true
244 | > Regex.compile!("mr. bojangles", "sxi") # ~r/mr. bojangles/sxi
245 | # Newline overrides
246 | > ~r/(*ANY)some\npattern/
247 | ```
248 |
249 | ## Collection Types
250 |
251 | ### List
252 | Simple linked lists that can be of any size and can have elements of any type.
253 | They are enclosed in `[ ]` and elements are comma separated.
254 | Concatenated with `++` and subtracted with `--`.
255 | Can be constructed with the cons operator `|`.
256 | Best for sequential access, fastest when elements are added and subtracted from the head.
257 | Instead of building a list by adding to its tail, add to the head and reverse the list.
258 | List implements the enumerable protocol so we use Enum for many common operations.
259 |
260 | ```elixir
261 | > [1, 2, 3.4, "a", "b", :c, [:d]]
262 | > [ 1 | [2 | [3]]] == [1, 2, 3] # true
263 | > [1, 2, 3.4] ++ ["a", "b", :c] # [1, 2, 3.4, "a", "b", :c]
264 | > [1, 2, 3.4, "a", "b", :c, [:d]] -- [2, "a", "c"] # [1, 3.4, "b", :c, [:d]]
265 | > hd [1, 2, 3] # 1
266 | > tl [1, 2, 3] # [2, 3]
267 | > length [:a, :b, :c, :d] # 4
268 | > Enum.reverse [:a, :b, :c] # [:c, :b, :a]
269 | > Enum.member? [:a, :b], :b # true
270 | > Enum.join [:a, :b], "_" # "a_b"
271 | > Enum.at [:a, :b, :c], 1 # :b
272 | ```
273 |
274 | ### Charlist
275 | A [List](#list) of UTF-8 codepoints.
276 | Other than syntax they are exactly the same as Lists and are not a unique class.
277 | Can span multiple lines and are delimited with single quotes `'`.
278 | Have the same [Escape Sequences](#escape-sequences) as String.
279 |
280 | ```elixir
281 | > 'char list'
282 | > [108, 105, 115, 116] == 'list' # true
283 | > 'turbo' ++ 'pogo' # 'turbopogo'
284 | > 'char list' -- 'a l' # 'christ'
285 | > hd 'such list' == ?s # true
286 | > String.to_char_list "tacosalad" # 'tacosalad'
287 | > List.to_string 'frijoles' # "frijoles"
288 | > [?Y, ?e, ?a, ?h] == 'Yeah' # true
289 | ```
290 |
291 | ### Tuple
292 | Can be of any size and have elements of any type.
293 | Elements are stored contiguously in memory.
294 | Enclosed in `{ }` and elements are comma separated.
295 | Fast for index-based access, slow for a large number of elements.
296 |
297 | ```elixir
298 | > { :a, 1, {:b}, [2]}
299 | > put_elem({:a}, 0, :b) # {:b}
300 | > elem({:a, :b, :c}, 1) # b
301 | > Tuple.delete_at({:a, :b, :c}, 1) # {:a, :c}
302 | > Tuple.insert_at({:a, :c}, 1, :b) # {:a, :b, :c}
303 | > Tuple.to_list({:a, :b, :c}) # [:a, :b, :c]
304 | ```
305 |
306 | ### Keyword List
307 | A List of 2 element Tuples where each Tuple's first element is an Atom.
308 | This atom is refered to as the keyword, or key.
309 | Have a special concice syntax that omits the Tuple's brackets and places the key's colon on the right.
310 | Being Lists they:
311 | - are order as specified
312 | - can have duplicate elements and multiple elements with the same key
313 | - are fastest when accessed at the head.
314 | - are concatenated with `++` and subtracted with `--`.
315 |
316 | Elements can be accessed with `[:key]` notation. The first Element with a matching `:key` will be returned.
317 | 2 Keyword Lists are only equal if all elements are equal and in the same order.
318 |
319 | ```elixir
320 | # Full Syntax
321 | > [{:a, "one"}, {:b, 2}]
322 | # Concice Syntax
323 | > [a: "one", b: 2]
324 | > [a: 1] ++ [a: 2, b: 3] == [a: 1, a: 2, b: 3] # true
325 | > [a: 1, b: 2] == [b: 2, a: 1] # false! elements are in different order
326 | > [a: 1, a: 2][:a] == 1 # true
327 | > Keyword.keys([a: 1, b: 2]) # [:a, :b]
328 | > Keyword.get_values([a: 1, a: 2], :a) # [1, 2]
329 | > Keyword.keyword?([{:a,1}, {:b,2}]) # true
330 | > Keyword.keyword?([{:a,1}, {"b",2}]) # false! "b" is not an Atom
331 | > Keyword.delete([a: 1, b: 2], :a) # [b: 2]
332 | ```
333 |
334 | ### Map
335 | Key - Value store where Keys and Values are of any type.
336 | Cannot have multiple values for the same key and are unordered.
337 | `Map`s are enclosed in `%{ }`, elements are comma seperated, and elemets have the form: key `=>` value.
338 | If all keys are `Atom`s, the `=>` can be omitted and the `Atom`'s `:` must be on the right.
339 | Values are accessed with `[key]` notation.
340 | Maps can be accessed with `.key` notation if key is an `Atom`.
341 | Maps can be updated by enclosing them in `%{}` and using the cons `|` operator.
342 | Maps can be of any size and are fastest for key based lookup.
343 |
344 | ```elixir
345 | > %{:a => 1, 1 => ["list"], [2,3,4] => {"a", "b"}}
346 | > %{:a => 1, :b => 2} == %{a: 1, b: 2} # true
347 | > %{a: "one", b: "two", a: 1} == %{a: 1, b: "two"} # true
348 | > %{a: "one", b: "two"} == %{b: "two", a: "one"} # true
349 | > %{a: "one", b: "two"}[:b] # "two"
350 | > %{a: "one", b: "two"}.b # "two"
351 | > %{a: "one", a: 1} == %{a: 1} # true
352 | > %{:a => "one", "a" => "two"}."a" == "two" # false! watchout
353 | > Map.keys( %{a: 1, b: 2} ) == [:a, :b] # true
354 | > %{ %{a: 1, b: 2, c: 3} | :a => 4, b: 5 } # %{a: 4, b: 5, c: 3}
355 | > Map.merge( %{a: 1, b: 2}, %{a: 4, c: 3} ) # %{a: 4, b: 2, c: 3}
356 | > Map.put( %{a: 1}, :b, 2 ) == %{a: 1, b: 2} # true
357 | > Kernel.get_in # TODO
358 | > Kernel.put_in # TODO
359 | ```
360 |
361 | ### Struct
362 | Structs can be thought of as bare Maps with pre-defined keys, default values and where the keys must be atoms.
363 | Structs are defined at the top level of a Module and take the Module's name.
364 | Structs do not implement the Access or Enumerable protocol and can be considered bare Maps.
365 | Structs have a special field called `__struct__` that holds the name of the struct.
366 |
367 | ```elixir
368 | defmodule City do
369 | defstruct name: "New Orleans", founded: 1718
370 | end
371 | nola = %City{}
372 | chi = %City{name: "Chicago", founded: 1833}
373 | nola.name # "New Orleans"
374 | chi.founded # 1833
375 | nola.__struct__ # City
376 | ```
377 |
378 | ### Range
379 | Used to specify the first and last elements of something.
380 | Just a Struct of type Range with a `first` field and a `last` field.
381 | Have a special `..` creation syntax but can also be created like any other struct.
382 |
383 | ```elixir
384 | > a = 5..10
385 | > b = Range.new(5, 10)
386 | > c = %Range{first: 5, last: 10}
387 | > Range.range?(c) # true
388 | > Enum.each(5..10, fn(n) -> n*n end) # prints all the squares of 5..10
389 | > Map.keys(5..10) # [:__struct__, :first, :last]
390 | > (5..10).first # 5
391 | ```
392 |
393 | ### Streams
394 | Lazy enumerables.
395 | Are created out of enumerables with functions in the `Stream` module.
396 | Elements are not computed until a method from the `Enum` module is called on them.
397 | ```elixir
398 | > a = Stream.cycle 'abc'
399 | #Function<47.29647706/2 in Stream.unfold/2> # Infinate Stream created
400 | > Enum.take a, 10 # Enum.take computes the 10 elements
401 | 'abcabcabca'
402 | ```
403 |
404 | With [Stream.unfold/2](http://elixir-lang.org/docs/stable/elixir/Stream.html#unfold/2) you can create an arbitrary stream.
405 | ```elixir
406 | > s = Stream.unfold( 5,
407 | fn 0 -> nil # returning nil halts the stream
408 | n -> {n, n-1} # return format {next-val, rest}
409 | end)
410 | > Enum.to_list(s)
411 | [5, 4, 3, 2, 1]
412 | ```
413 |
414 | ## Syntax
415 |
416 | ### Variables
417 | Are declared and initialized upon use.
418 | Are named in the following format:
419 |
420 | 
421 | Can hold any data structure and can be assigned more than once.
422 |
423 | ```elixir
424 | > something = :anything
425 | > something = ["a", "list", "of", "strings"]
426 | > _yeeHaw1234! = %{:a => :b}
427 | ```
428 |
429 | ### Operators
430 | #### Standard infix
431 | - Equality `==`, `!=`
432 | - Strict equality `===` and `!==` do not coerce Floats to Integers. `1 === 1.0 #false`
433 | - Comparison `>`, `<`, `>=`, `<=`
434 | - Logic, short-circuiting `&&` and `||`
435 | - Boolean only Logic, short-circuiting `and` and `or`. (Only left side must be boolean)
436 | - Math `+`, `-`, `*`, `/`
437 |
438 | #### Standard prefix
439 | - Negation, any type `!`, `!1 == false`
440 | - Negation, boolean only `not`, `not is_atom(5) == true`
441 |
442 | #### = (match)
443 | left `=` right
444 | Performs a [Pattern Match](#pattern-matching).
445 |
446 | #### ^ (pin)
447 | Used to pin the value of a variable in the left side of a [Pattern Match](#pattern-matching).
448 | ```elixir
449 | a = "thirty hams"
450 | {b, ^a} = {:i_need, "thirty hams"} # `b` is set to `:i_need`
451 | {^a, {^a}} = {"thirty hams", {"thirty hams"}} # nothing is set, but the match succedes
452 | ```
453 |
454 | #### |> (pipe)
455 | `|>`
456 | Takes the result of a statement on its left and passes as the first argument to the function on its right.
457 | The statement on the left can be on the preceeding line of code.
458 | ```elixir
459 | > [1,2,3] |> hd |> Integer.to_string |> IO.inspect # "1"
460 | # ⇣ doesn't work in iex
461 | hd([1,2,3])
462 | |> Integer.to_string
463 | |> IO.inspect # "1"
464 | ```
465 |
466 | #### =~ (string match)
467 | `=~`
468 | Takes a string on the left and on the right either a string or a regular expression.
469 | If the string on the right is a substring of left, `true` is returned.
470 | If the regular expression on the right matches the string on the left, `true` is returned.
471 | Otherwise `false` is returned.
472 | ```elixir
473 | > "abcd" =~ ~r/c(d)/ # true
474 | > "abcd" =~ ~r/e/ # false
475 | > "abcd" =~ "bc" # true
476 | > "abcd" =~ "ad" # false
477 | ```
478 |
479 | #### ? (codepoint)
480 | `?`
481 | Returns the UTF-8 codepoint of the character immediately to its right.
482 | Can only take one character, accepts [Escape Sequences](#escape-sequences).
483 | **Remember** [Charlists](#charlist) are just lists of UTF-8 codepoints.
484 | ```elixir
485 | > ?a # 97
486 | > ?♫ # 9835
487 | > ?\s # 32
488 | > ?? # 63
489 | > [?♀, ?!] == '♀!' # true
490 | ```
491 |
492 | #### & (capture)
493 | - TODO
494 |
495 | #### Ternary
496 | Elixir has no ternary operator. The same effect though can be achieved with the `if` macro.
497 | ```elixir
498 | > a = if true, do: "True!", else: "False!"
499 | > a == "True!" # true
500 | ```
501 |
502 | #### in
503 | left `in` right.
504 | Used to check if the **enumerable** on the right contains the data structure on the left.
505 | Right hand side must implement the Enumerable Protocol.
506 |
507 | ```elixir
508 | > :b in [:a, :b, :c] # true
509 | > [:c] in [1,3,[:c]] # true
510 | > :ok in {:ok} # ERROR: protocol Enumerable not implemented for {:ok}
511 | ```
512 |
513 | ### Comments
514 | `#` indicates that itself and anything after it until a new line is a comment. That is all.
515 |
516 | ### Semicolons
517 | Semicolons can be used to terminate statements but in practice are rarely if ever used.
518 | The only required usage is to put more than one statement on the same line. `a = 1; b = 2`
519 | This is considered bad style and placing them on seperate lines is much prefered.
520 |
521 | ### Do, End
522 | Blocks of code passed to macros start with `do` and end with `end`.
523 | ```elixir
524 | if true do
525 | "True!"
526 | end
527 |
528 | if true do "True!" end
529 |
530 | # inside a module
531 | def somefunc() do
532 | IO.puts "multi line"
533 | end
534 |
535 | if true do
536 | "True!"
537 | else
538 | "False!"
539 | end
540 | ```
541 |
542 | You can pass the block as a single line and without `end` with some extra puctuation.
543 | ```elixir
544 | # ⇣ ⇣ ⇣ no end keyword
545 | if true, do: "True!"
546 | # ⇣ ⇣ ⇣ ⇣ ⇣ no end keyword
547 | if true, do: "True", else: "False!"
548 | # inside a module
549 | # ⇣ ⇣ ⇣ no end keyword
550 | def someFunc(), do: IO.puts "look ma, one line!"
551 | ```
552 |
553 | Syntactic sugar for
554 | ```elixir
555 | if(true, [{:do, "True!"}, {:else, "False!"}])
556 | def(someFunc(), [{:do, IO.puts "look ma, one line!"}])
557 | ```
558 |
559 | ### Pattern Matching
560 | A match has 2 main parts, a **left** side and a **right** side.
561 | ```elixir
562 | # ┌Left ┌Right
563 | # ┌───┴───┐ ┌───┴──────┐
564 | {:one, x} = {:one, :two}
565 | # ┌Right
566 | # ┌───┴──────┐
567 | case {:one, :two} do
568 | # ┌Left
569 | # ┌───┴───┐
570 | {:one, x} -> IO.puts x
571 | # ┌Left
572 | _ -> IO.puts "no other match"
573 | end
574 | ```
575 |
576 | The **right** side is a **data structure** of any kind.
577 | The **left** side attempts to **match** itself to the **data structure** on the right and **bind** any **variables** to **substructures**.
578 |
579 | The simplest **match** has a lone **variable** on the **left** and will **match** anything:
580 | ```elixir
581 | # in these examples `x` will be set to whatever is on the right
582 | x = 1
583 | x = [1,2,3,4]
584 | x = {:any, "structure", %{:whatso => :ever}}
585 | ```
586 |
587 | But you can place the **variables** inside a **structure** so you can **capture** a **substructure**:
588 | ```elixir
589 | # `x` gets set to only the `substructure` it matches
590 | {:one, x} = {:one, :two} # `x` is set to `:two`
591 | [1,2,n,4] = [1,2,3,4] # `n` is set to `3`
592 | [:one, p] = [:one, {:apple, :orange}] # `p` is set to `{:apple, :orange}`
593 | ```
594 |
595 | There is also a special `_` **variable** that works exactly like other **variables** but tells elixir, "Make sure something is here, but I don't care exactly what it is.":
596 | ```elixir
597 | # in all of these examples, `x` gets set to `:two`
598 | {_, x} = {:one, :two}
599 | {_, x} = {:three, :two}
600 | [_,_,x,_] = [1,{2},:two,3]
601 | ```
602 |
603 | If you place a **variable** on the **right**, its **value** is used:
604 | ```elixir
605 | # ┌Same as writing {"twenty hams"}
606 | a = {"twenty hams"} ⇣
607 | {:i_have, {b}} = {:i_have, a} # `b` is set to "twenty hams"
608 | ```
609 |
610 | In the previous example you are telling elixir: I want to **match** a **structure** that is a **tuple**, and this **tuple's** first element is going to be the atom **:i_have**. This **tuple's** second element is going to be a **tuple**. This **second tuple** is going to have one element and whatever it is I want you to bind it to the variable **b**.
611 |
612 | If you want to use the **value** of a **variable** in your structure on the **left** you use the `^` operator:
613 | ```elixir
614 | a = "thirty hams"
615 | {b, ^a} = {:i_need, "thirty hams"} # `b` is set to `:i_need`
616 | {^a, {^a}} = {"thirty hams", {"thirty hams"}} # nothing is set, but the match succedes
617 | ```
618 |
619 | #### Maps
620 | Individual keys can be matched in Maps like so:
621 | ```elixir
622 | nola = %{ name: "New Orleans", founded: 1718 }
623 | %{name: city_name} = nola # city_name now equals "New Orleans"
624 | %{name: _, founded: city_founded} = nola # Map must have both a name and a founded key
625 | ```
626 | You can use the pin operator (^) to match on variables:
627 | ```elixir
628 | field = "founded"
629 | %{^field: city_founded} = nola # city_founded now equals 1718
630 | ```
631 |
632 | #### Binaries
633 | - `<< size::8, rest::binary>> = <<3,0,25,1,1,2,1,6,4,3>>`
634 | - `<< data::size(size)-unit(16)-binary, rest::binary>> = rest`
635 | - TODO
636 |
637 | #### Ranges
638 | Ranges can be pattern matched if both their values are integers.
639 | ```elixir
640 | min..max = 20..5000
641 | min == 20 # true
642 | max == 5000 # true
643 | min..max == 1..10.0 # Thats an Argument Error
644 | ```
645 |
646 | ### Reserved words
647 | These words are reserved for the language and cannot be used as variables, module or method names.
648 |
649 | `nil`, `true`, `false`, `__MODULE__`,`__FILE__`,`__DIR__`,`__ENV__`,`__CALLER__`
650 |
651 | ## Truthiness
652 | `:nil` and `:false` are falsy.
653 | `nil` and `false` are syntactic sugar for `:nil` and `:false`.
654 | Everything else is truthy.
655 |
656 | ```elixir
657 | > !!nil # false
658 | > !!0 # true
659 | > nil || :nil || false || :false || 1 # 1
660 | ```
661 |
662 | ## Sorting
663 | Any types can be compared using comparison operators.
664 | `number < atom < reference < functions < port < pid < tuple < maps < list < bitstring`
665 |
666 | ```elixir
667 | 10000 < :five == true
668 | "something" > &div/2 == true
669 | ```
670 |
671 | ## Modules
672 | Modules organize code under a namespace.
673 | They can be meta-programmed but are defined at compile time and cannot be changed after, only replaced .
674 | Named according to the following format:
675 |
676 | 
677 |
678 | ### Declaration
679 | ```elixir
680 | defmodule MyModule do
681 | end
682 | ```
683 |
684 | ### Module Functions
685 | Names must begin with `a-z`.
686 | Names can contain `a-Z`, `A-Z`, `0-9` and `_`.
687 | May end with `?` or `!`.
688 |
689 | ```elixir
690 | defmodule MyModule do
691 | def my_function do
692 | IO.puts("Hello from my function")
693 | end
694 | end
695 | ```
696 |
697 | `def` is actually a macro, and like calling any macro, [do ... end](#do-end) can be written as a one liner:
698 | ```elixir
699 | defmodule MyModule do
700 | def my_function, do: IO.puts("Hello from my function")
701 | end
702 | ```
703 |
704 | Inside of the defining module, functions may be called by name. Outside they must be called with the defining Module's name and a `.`. Eg: `IO.puts()`
705 | ```elixir
706 | defmodule MyModule do
707 | def function1 do
708 | IO.puts "func 1"
709 | end
710 | def function2 do
711 | function1
712 | IO.puts "funct 2"
713 | end
714 | end
715 |
716 | > MyModule.function2
717 | ```
718 |
719 | Arguments are passed to functions positionally and can have default arguments.
720 | Arguments can be of any Type.
721 | ```elixir
722 | defmodule MyModule do
723 | # ⇣ indicates "earthlings" to be the default for who
724 | def greet(greeting, who \\ "earthlings") do
725 | IO.puts("#{greeting} #{who}")
726 | end
727 | end
728 |
729 | > MyModule.greet("'sup", "y'all?") # "'sup y'all?"
730 | > MyModule.greet("greetings") # "greetings earthlings"
731 | ```
732 |
733 | Module functions can be defined multiple times to support different configurations of arguments.
734 | ```elixir
735 | defmodule MyModule do
736 | def greet() do
737 | greet("hello", "you")
738 | end
739 | def greet(greeting, who) do
740 | IO.puts("#{greeting} #{who}")
741 | end
742 | end
743 |
744 | > MyModule.printer("hello") # "hello"
745 | > MyModule.printer([1,2,3]) # [1,2,3]
746 | > MyModule.printer() # "nothing passed"
747 | ```
748 |
749 | They can also be defined multiple times to Pattern Match on arguments passed.
750 | ```elixir
751 | def is_it_the_number_2?(2) do
752 | true
753 | end
754 | def is_it_the_number_2(value) do
755 | false
756 | end
757 | ```
758 |
759 | You can ignore arguments with `_` and our previous example is better written as
760 | ```elixir
761 | def is_it_the_number_2?(2) do
762 | true
763 | end
764 | # ⇣ underscore ignores argument
765 | def is_it_the_number_2(_) do
766 | false
767 | end
768 | ```
769 |
770 | Module function definitions can have [Guards](#guards).
771 | ```elixir
772 | def square(n) when is_number(n), do: n * n
773 | def square(_), do: raise "not a number"
774 | ```
775 |
776 | ### Private Functions
777 | To make a function private to a module use `defp` instead of `def`.
778 |
779 | ```elixir
780 | defmodule ModA do
781 | defp hi, do: IO.puts "Hello from ModA"
782 | def say_hi, do: hi
783 | end
784 | ModA.say_hi
785 | # Hello from ModA
786 | ModA.hi
787 | # ** (UndefinedFunctionError) undefined function ModA.hi/0 ModA.hi()
788 | ```
789 |
790 | ### Working with other modules
791 | Inside of a module you can use one of the 4 directives to interact with other modules.
792 | #### import
793 | `import SomeModule` brings all modules and macros of SomeModule into the enclosing module so you can use them un-namespaced
794 | `import` can take either an `only:` or `except:` list in which you specify functions and macros to include.
795 | Alternatively `import SomeModule, only:` can take `:functions` or `:macros` to specify only those.
796 | ```elixir
797 | def ModA do
798 | import ModB # All Functions and Macros in ModB
799 | import ModB, except: [destroy_planet: 1] # All Functions and Macros except destroy_planet/1
800 | import ModB, only: :functions # All functions, no macros
801 | import ModB, only: [say_hi: 0, fibonacci: 1] # Only the specified functions or macros
802 | end
803 | ```
804 |
805 | #### require
806 | `require SomeModule` allows you to use macros of SomeModule. It also makes sure that SomeModule is compiled before the enclosing module.
807 |
808 | #### use
809 | `use SomeModule` first __requires SomeModule__ and then calls the macro SomeModule.\_\_using\_\_. It is often used to perform setup for metaprogramming.
810 |
811 | #### alias
812 | `alias SomeVery.Long.ModuleName, as: SVLMN` is used simply to shorten a module name to cut down on typing.
813 |
814 | ### Attributes
815 | Pieces of data that can be thought of as metadata or constants for a module.
816 | They are inlined by the compiler and cannot be changed at runtime.
817 | They can be set multiple times and the value used will be the value set when the function is defined.
818 |
819 | ```elixir
820 | defmodule ModA do
821 | @name "April"
822 | def first, do: @name
823 | @name "O'Neal"
824 | def last, do: @name
825 | end
826 | ```
827 |
828 | TODO:
829 | - @external_resource
830 | - Better explanation of attributes in relation to metaprogramming
831 |
832 | ### Documentation
833 | Elixir has documentation built in and you can document your modules and functions with Attributes.
834 | `@moduledoc` describes your module.
835 | `@doc` describes module functions.
836 | ```elixir
837 | defmodule MathUtils do
838 | @moduledoc """
839 | Random math related functions
840 | """
841 |
842 | @doc "Squares the given number."
843 | def square(n), do: n*n
844 | end
845 | ```
846 |
847 | ### Introspection
848 | - `__info__(:functions)`
849 |
850 | ## Errors
851 | Only to be used in exceptional circumstances, not for control flow.
852 | Built in errors are listed in the docs: http://elixir-lang.org/docs/stable/elixir/ArgumentError.html . They're on the left.
853 |
854 | ### Raise
855 | `raise` a runtime error:
856 | ```elixir
857 | > raise "not fabulous enough"
858 | ** (RuntimeError) not fabulous enough
859 | ```
860 |
861 | `raise` a different error:
862 | ```elixir
863 | > raise ArgumentError, "I'm done. We're talking in circles."
864 | #** (ArgumentError) I'm done. We're talking in circles.
865 | ```
866 |
867 | Some errors take specific options, and you must read the source to find them:
868 | ```elixir
869 | > raise KeyError, key: "to car", term: "pocket"
870 | #** (KeyError) key "to car" not found in: "pocket"
871 | ```
872 |
873 | ### Custom Error
874 | ``` elixir
875 | defmodule LandWarWithRussiaError do
876 | defexception message: "Never."
877 | end
878 | > raise LandWarWithRussiaError
879 | #** (LandWarWithRussiaError) Never.
880 | ```
881 |
882 | ### Rescue
883 | ```elixir
884 | try do
885 | if false do
886 | raise "are we there yet?"
887 | else
888 | raise ArgumentError, "I'll pull this car around!"
889 | end
890 | rescue
891 | e in RuntimeError -> IO.puts "No!"
892 | e in ArgumentError -> IO.puts "That's it we're going home!"
893 | end
894 | ```
895 |
896 | **Remember** There are much better ways to control flow in Elixir than raising/rescuing errors.
897 | Errors should be reserved for truly exceptional situations.
898 |
899 |
900 | ## Control Flow
901 | ### if/unless
902 | ```elixir
903 | if :something_truthy do
904 | IO.puts "something truthy happened"
905 | else
906 | IO.puts "false or nil happened"
907 | end
908 |
909 | unless :something_truthy do
910 | IO.puts "nil or false happened"
911 | else
912 | IO.puts "something truthy happened"
913 | end
914 | ```
915 |
916 | ### case
917 | `case` let's you pattern match on a value.
918 | If no cases match it throws a `MatchError`.
919 | ```elixir
920 | case 137 do
921 | "137" -> IO.puts "I require 137 the number."
922 | 137 -> IO.puts "Ahh much better."
923 | 138 ->
924 | IO.puts "Blocks can start on the next line as well."
925 | end
926 | ```
927 |
928 | Like all pattern matches, `_` will match anything and can be used as a catchall:
929 | ```elixir
930 | case {:ok, "everything went to plan"} do
931 | {:ok, message} -> IO.puts message
932 | {:error, message} -> IO.puts "ERROR!: #{message}"
933 | # ⇣catchall, otherwise you'll get an error if nothing matches
934 | _ -> IO.puts "I match everything else!"
935 | end
936 | ```
937 |
938 | You can have [guards](#guards) on your cases:
939 | ```elixir
940 | case 1_349 do
941 | n when is_integer n -> IO.puts "you gave me an integer"
942 | n when is_binary n -> IO.puts "you gave me a binary"
943 | _ -> IO.puts "you gave me neither an integer nor binary"
944 | end
945 | ```
946 |
947 | ### cond
948 | `cond` takes one or more conditions and runs the first truthy one it finds.
949 | Often used where imperative languages would use elseif.
950 | If no statements evaluate to true it throws a `MatchError`.
951 | ```elixir
952 | cond do
953 | false -> IO.puts "I will never run"
954 | true -> IO.puts "I will always run"
955 | 1235 -> IO.puts "I would run if that dang true wasn't on top of me."
956 | end
957 | ```
958 |
959 | `true` is often used as a catch all:
960 | ```elixir
961 | guess = 12
962 | cond do
963 | guess == 10 -> IO.puts "You guessed 10!"
964 | guess == 46 -> IO.puts "You guessed 46!"
965 | true ->
966 | IO.puts "I give up."
967 | end
968 | ```
969 | ### throw/catch
970 | Inside of a `try` block you can `throw` any data type and pattern match on it inside a `catch` block.
971 | `catch` blocks work the same as [case](#case) blocks.
972 | `after` blocks will always run, throw or no throw.
973 | ```elixir
974 | try do
975 | IO.puts "Inside a try block"
976 | throw [:hey, "Reggie"]
977 | IO.puts "if there is a throw before me, I'll never run."
978 | catch
979 | x when is_number(x) -> IO.puts "!!A number was thrown."
980 | [:hey, name] -> IO.puts "!!Hey was thrown to #{name}."
981 | _ -> IO.puts "Something else was thrown."
982 | after
983 | IO.puts "I run regardless of a throw."
984 | end
985 | ```
986 |
987 | ### with
988 | Takes a series of pattern matches, runs them in order, if all pattern matches succeed it returns its `do` block. If a pattern match doesn't succeed, the non-matching value is returned and `with` is exited.
989 | You can supply an `else` block that essentially functions as a `case` block for an uncussessful match.
990 | Variables assigned in a `with` block do not leak into outer scope.
991 | A comma must come after every match.
992 |
993 | ```elixir
994 | nums = [8,13,44]
995 | # ┌left arrow ┌comma
996 | # match left | match right |
997 | # ┌───┴────┐ ⇣ ┌───────┴─────────┐⇣
998 | with {:ok, num} <- Enum.fetch(nums, 2),
999 | "44" <- Integer.to_string(num),
1000 | do: "it was 44"
1001 |
1002 | # Paterns can take guards
1003 | with a when is_nil(a) <- nil,
1004 | do: "Accepts guards"
1005 | else
1006 | _ -> "Does not accept guards"
1007 |
1008 | # From the docs
1009 | opts = %{width: 10, height: 15}
1010 | with {:ok, width} <- Map.fetch(opts, :width),
1011 | {:ok, height} <- Map.fetch(opts, :height),
1012 | do: {:ok, width * height}
1013 | # returns {:ok, 150}
1014 |
1015 | opts = %{width: 10}
1016 | with {:ok, width} <- Map.fetch(opts, :width),
1017 | {:ok, height} <- Map.fetch(opts, :height),
1018 | do: {:ok, width * height}
1019 | # returns :error as that's what Map.fetch returns when a key is not present.
1020 | # ┌─ Or you can catch the error in an else block
1021 | else
1022 | :error -> "A key wasn't found!"
1023 |
1024 | ```
1025 |
1026 | ## Guards
1027 | TODO: how to use guards.
1028 | Errors generated in guards are swallowed and simply cause the guard to fail.
1029 | Functions and operators allowed in guard clauses:
1030 |
1031 | | = | logic | math | type_checking | map | tuple |list |binary | Kernel
1032 | |-----------|-------|-------|---------------|-----------|------------|---------|-----------|--------
1033 | |== | or | + | is_atom | map_size()|elem() |a `in` b |bit_size() | node()
1034 | |!= | and | - | is_binary | |tuple_size()|hd() |byte_size()| self()
1035 | |=== | not | * | is_bitstring | | |tl() | |
1036 | |!== | | / | is_boolean | | |length() | |
1037 | |\> | |abs() | is_exception |||||
1038 | |\< | |div() | is_float |||||
1039 | |\<= | |float()| is_function |||||
1040 | |\>= | |rem() | is_integer |||||
1041 | | | |round()| is_nil |||||
1042 | | | |trunc()| is_list |||||
1043 | | | | | is_number |||||
1044 | | | | | is_pid |||||
1045 | | | | | is_port |||||
1046 | | | | | is_reference |||||
1047 | | | | | is_tuple |||||
1048 |
1049 | **Notice** `!`, `&&` and `||` are not allowed in guard clauses.
1050 |
1051 | ## Anonymous Functions
1052 | Closures in which the captured variables are set at definition.
1053 | Are essentially [case](#case) blocks you can pass around.
1054 | Take the general form:
1055 | ```elixir
1056 | fn (1, 2, 3) -> IO.inspect 1*2*3
1057 | (a, b, c) -> IO.inspect [a,b,c]
1058 | end
1059 | ```
1060 | Are called with the `.` operator.
1061 | ```elixir
1062 | > add_2 = fn num -> num + 2 end
1063 | # ⇣called with a dot
1064 | > add_2.(127) == 129
1065 | true
1066 | > three = 3
1067 | > add_3 = fn num -> num + three end
1068 | > add_3.(262) == 265
1069 | true
1070 | # ⇣is our function compromised?
1071 | > three = 7
1072 | # ⇣no, `three` is still 3 in the function
1073 | > add_3.(262) == 265
1074 | true
1075 | ```
1076 |
1077 | Like case blocks, they can have multiple matches, matches can have guards, and do not leak scope:
1078 | ```elixir
1079 | > support_method = fn ("suspenders") -> IO.puts "Hey big spender."
1080 | ("belt") -> IO.puts "Who is the real hero?"
1081 | a when is_list a -> Enum.each(a, support_method)
1082 | _ -> IO.puts "What is this wizzardry?"
1083 | end
1084 | > support_method.(["belt", "suspenders"])
1085 | "Who is the real hero?"
1086 | "Hey big spender."
1087 | > peanut_butter = "smooth"
1088 | # ⇣immediately call
1089 | > fn () -> peanut_butter = "chunky" end.()
1090 | > peanut_butter == "smooth"
1091 | true # scope was not leaked
1092 | ```
1093 |
1094 | They **cannot** have multiple arities (which in case statements wouldn't make sense):
1095 | ```elixir
1096 | > fn (a) -> "One"
1097 | (a, b) -> "Two"
1098 | end
1099 | # That's a compile error
1100 | ```
1101 |
1102 | ## Comprehensions
1103 | Loop over any enumerable or bitstring and build another.
1104 | By default they build lists.
1105 | `generators`, `filters` and `into:` are comma separated. `do` follows [Do, End](#do-end) rules.
1106 | Basic form:
1107 | ```elixir
1108 | # ┌for ┌Generator ┌Block
1109 | # ⇣ ┌────────┴────────┐┌──────┴──────┐
1110 | > for num <- [1, 2, 3, 4], do: num * num
1111 | [1, 4, 9, 16]
1112 | ```
1113 |
1114 | They can have filters:
1115 | ```elixir
1116 | # ┌Filter
1117 | # ┌────────┴───────┐
1118 | > for num <- [1, 2, 3, 4], rem(num, 2) == 0, do: num * num
1119 | [4, 16]
1120 | ```
1121 |
1122 | Multiple generators:
1123 | ```elixir
1124 | # ┌Generator ┌Generator
1125 | # ┌──────┴─────┐┌─────────┴───────┐
1126 | > for num <- [1,2,3], str <- ["a", "b"], do: "#{num}#{str}"
1127 | ["1a", "1b", "2a", "2b", "3a", "3b"]
1128 | ```
1129 |
1130 | Multiple filters:
1131 | ```elixir
1132 | # ┌Filter ┌Filter
1133 | # ┌─────┴───┐┌──────┴────┐
1134 | > for num <- [1,2,3], str <- ["a", "b"], num !== 3, str !== "a", do: "#{num}#{str}"
1135 | ["1b", "2b"]
1136 | ```
1137 |
1138 | You can pattern match in generators:
1139 | ```elixir
1140 | > for {_, age} <- %{doug: 4, lucy: 6, ralf: 10}, do: age
1141 | [4, 6, 10]
1142 | ```
1143 |
1144 | You can build a different data structure with `into`:
1145 | ```elixir
1146 | # ┌Into a map
1147 | # ┌────┴────┐
1148 | > for num <- [1, 2, 3, 4], into: %{}, do: {num, num*num}
1149 | %{1 => 1, 2 => 4, 3 => 9, 4 => 16}
1150 | # ┌Into a string
1151 | # ┌────┴───┐
1152 | > for num <- [1, 2, 3, 4], into: "", do: "the square of #{num} is #{num * num}. "
1153 | "the square of 1 is 1. the square of 2 is 4. the square of 3 is 9. the square of 4 is 16. "
1154 | ```
1155 |
1156 | Enumerating binaries is a breeze though they have a special syntax:
1157 | ```elixir
1158 | # ┌Binary generator
1159 | # ┌────────────┴─────────────────┐
1160 | > for <> >>, do: byte
1161 | [255, 12, 55, 89]
1162 | # ┌Pattern Match on bit size
1163 | # ┌───┴───┐
1164 | > for <> >>, do: bit
1165 | [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0]
1166 |
1167 | > pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
1168 | # ⇣Short hand for bit-size
1169 | > for <>, do: {r, g, b}
1170 | [{213,45,132},{64,76,32},{76,0,0},{234,32,15}]
1171 | ```
1172 |
1173 | Work well with streams:
1174 | ```elixir
1175 | # Grabs 5 lines of input and upcases it
1176 | stream = IO.stream(:stdio, :line)
1177 | for line <- Enum.take(stream, 5), into: stream do
1178 | String.upcase(line)
1179 | end
1180 | ```
1181 |
1182 | ## Sigils
1183 | Sigils create structures out of text passed to them.
1184 | They take the general form `~type| content |m` and can be delimited by `{}`, `[]`, `()`, `//`, `||`, `""`, or `''`.
1185 | Built in sigils:
1186 |
1187 | Creates | With Interpolation | Without Interpolation
1188 | ------------------|:------------------:|:---------------------:|
1189 | String | s | S
1190 | Charlist | c | C
1191 | List of words | w | W
1192 | Regular Expression| r | R
1193 |
1194 | ```elixir
1195 | > a = "Yay!"
1196 | > ~s|Quotes #{a} 'used' "willy nilly.| # "Quotes Yay! 'used' \"willy nilly."
1197 | > ~S{Not "interpolated" #{a}} # "Not \"interpolated\" \#{a}"
1198 | > ~c[charlist "with" 'quotes' #{a}] # 'charlist "with" \'quotes\' Yay!'
1199 | > ~w/a list of words #{a}/ # ["a", "list", "of", "words", "Yay!"]
1200 | > ~W"a list of words #{a}" # ["a", "list", "of", "words", "\#{a}"]
1201 | ```
1202 |
1203 | The `~w` and `~W` sigils can take modifier to specify which type of value to create, `a`, `c`, or `s` for `atom` `charlist` or `string`.
1204 |
1205 | ```elixir
1206 | > ~w|alpha bravo charlie|a # [:alpha, :bravo, :charlie]
1207 | > ~w|alpha bravo charlie|c # ['alpha', 'bravo', 'charlie']
1208 | > ~w|alpha bravo charlie|s # ["alpha", "bravo", "charlie"]
1209 | ```
1210 |
1211 | You can also define custom Sigils:
1212 | ```elixir
1213 | defmodule MySigil do
1214 | def sigil_i(string, 'd') do
1215 | for num <- String.split(string), do: String.to_integer(num) * 2
1216 | end
1217 | def sigil_i(string, _opts) do
1218 | for num <- String.split(string), do: String.to_integer(num)
1219 | end
1220 | end
1221 | > import MySigil
1222 | > ~i|1 2 3 4 5| # [1, 2, 3, 4, 5]
1223 | > ~i|1 2 3 4 5|d # [2, 4, 6, 8, 10]
1224 | ```
1225 |
1226 | ## Metaprogramming
1227 | - macros
1228 | - quote
1229 | - unquote
1230 | - var!
1231 |
1232 | ## Processes
1233 |
1234 | ## Structs
1235 | - %ModuleName{}
1236 | - implement Map behaviour
1237 | - Pattern matching on structs
1238 | - @derive
1239 |
1240 | ## Working with Files
1241 |
1242 | ## Erlang Interoperability
1243 | Erlang modules can be called by prepnding them with a colon.
1244 | ```elixir
1245 | :crypto.hash(:sha, "Elixir is the beez knees")
1246 | |> :crypto.bytes_to_integer
1247 | |> Integer.to_string(16) # "62A3326DEDE3EE38C9C85ED6EC87FD888A130D24"
1248 | ```
1249 |
1250 | ## IEx
1251 | Interactive Elixir. An Elixir REPL that comes with your Elixir install
1252 |
1253 | ### Running
1254 | run `iex` from a command prompt to enter iex.
1255 | `iex some_file.ex` will compile ./some_file.ex and load it into iex.
1256 |
1257 | ### Using
1258 | iex has built in tab completion. Press tab at an empty prompt to see all functions available.
1259 |
1260 | #### Some useful functions
1261 | - h/0 : Documentation for IEx helpers
1262 | - h/1 : Documentation for a Module or Function
1263 | - i/1 : Inforamtion about a value
1264 | - c/1 : Compile and load a file
1265 | - r/1 : Reload a module
1266 |
1267 | TODO:
1268 | - `-S mix`
1269 |
1270 | ## Mix
1271 | Task runner, build tool, testing harness.
1272 | Run `mix help` from the command line for more details.
1273 |
1274 | ### Applications
1275 | `mix new PATH` generates the boilerplate for an elixir application.
1276 | Run `mix help new` for more details.
1277 |
1278 | ### Tasks
1279 | Mix tasks are modules under the `Mix.Task` namespace that `use Mix.Task` and implement a `run/1` function.
1280 | If you want your task to show up when `mix help` is run you must include a `@shortdoc`.
1281 | `@moduledoc` gets displayed when `mix help sometask` is run.
1282 | A base mix task file looks like:
1283 | ```elixir
1284 | defmodule Mix.Tasks.MyTask do
1285 | use Mix.Task
1286 | @shortdoc "Boilerplate for a task"
1287 | @moduledoc """
1288 | This task just echos out the options passed to it.
1289 | """
1290 | def run(opts) do
1291 | IO.inspect(opts)
1292 | end
1293 | end
1294 | ```
1295 |
1296 | Elixir has a built in option parser that you should use for such a task:
1297 | http://elixir-lang.org/docs/stable/elixir/OptionParser.html
1298 |
1299 | ## Tests
1300 | Testing is built into the elixir platform via [ExUnit](http://elixir-lang.org/docs/stable/ex_unit/).
1301 | You can define tests in two ways.
1302 | If you are in a Mix Application, you put tests in files under the `test` directory.
1303 | These tests will be run with `mix test`.
1304 | You can also place tests at the end of any elixir file and they will be run on compilation.
1305 | Test boilerplate looks like:
1306 | ```elixir
1307 | # ⇣ not needed if in a mix project, setup for you in test_helper.exs
1308 | ExUnit.start
1309 |
1310 | defmodule MyModuleTest do
1311 | use ExUnit.Case
1312 |
1313 | test "the truth" do
1314 | assert 1 + 1 == 2
1315 | end
1316 | end
1317 | ```
1318 |
1319 | ### Debugging in the context of a test
1320 |
1321 | 1. First add to the top of your test file (before `defmodule`):
1322 | ```elixir
1323 | require IEx
1324 | ```
1325 |
1326 | 2. Inside your test, where you want to break into IEx, add:
1327 | ```
1328 | IEx.pry
1329 | ```
1330 |
1331 | 3. Run your tests with this invocation:
1332 | ```elixir
1333 | iex -S mix test --trace
1334 | ```
1335 | The `--trace` prevents iex from timing out after you've broken into pry.
1336 |
1337 |
1338 | ## Style Guide
1339 | - Module, record, protocol and behaviour names start with an initial cap and are BumpyCase.
1340 | - Ex: MyModule
1341 | - All other identifiers start with a lowercase letter or an underscore and are snake_case.
1342 | - Ex: in_the_air_tonight
1343 | - For indentation use 2 spaces. No Tabs.
1344 |
1345 |
1346 | **Notes**
1347 | - Regex images generated here: http://jex.im/regulex/
1348 |
--------------------------------------------------------------------------------
/images/atom-naming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsgreggreg/elixir_quick_reference/167c37fd08bbc91188990981b0569a965e3687eb/images/atom-naming.png
--------------------------------------------------------------------------------
/images/module-naming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsgreggreg/elixir_quick_reference/167c37fd08bbc91188990981b0569a965e3687eb/images/module-naming.png
--------------------------------------------------------------------------------
/images/variable-naming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsgreggreg/elixir_quick_reference/167c37fd08bbc91188990981b0569a965e3687eb/images/variable-naming.png
--------------------------------------------------------------------------------