File: learnelixir.exs.fold

package info (click to toggle)
kf6-syntax-highlighting 6.13.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 47,568 kB
  • sloc: xml: 197,750; cpp: 12,850; python: 3,023; sh: 955; perl: 546; ruby: 488; pascal: 393; javascript: 161; php: 150; jsp: 132; lisp: 131; haskell: 124; ada: 119; ansic: 107; makefile: 96; f90: 94; ml: 85; cobol: 81; yacc: 71; csh: 62; erlang: 54; sql: 51; java: 47; objc: 37; awk: 31; asm: 30; tcl: 29; fortran: 18; cs: 10
file content (485 lines) | stat: -rw-r--r-- 19,762 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# Original: https://learnxinyminutes.com/docs/elixir/

# Single line comments start with a number symbol.

# There's no multi-line comment,
# but you can stack multiple comments.

# To use the elixir shell use the `iex` command.
# Compile your modules with the `elixirc` command.

# Both should be in your path if you installed elixir correctly.

## ---------------------------
## -- Basic types
## ---------------------------

# There are numbers
3    # integer
0x1F # integer
3.0  # float

# Atoms, that are literals, a constant with name. They start with `:`.
:hello # atom

# Tuples that are stored contiguously in memory.
<beginfold id='1'>{</beginfold id='1'>1,2,3<endfold id='1'>}</endfold id='1'> # tuple

# We can access a tuple element with the `elem` function:
elem<beginfold id='2'>(</beginfold id='2'><beginfold id='1'>{</beginfold id='1'>1, 2, 3<endfold id='1'>}</endfold id='1'>, 0<endfold id='2'>)</endfold id='2'> #=> 1

# Lists that are implemented as linked lists.
<beginfold id='3'>[</beginfold id='3'>1,2,3<endfold id='3'>]</endfold id='3'> # list

# We can access the head and tail of a list as follows:
<beginfold id='3'>[</beginfold id='3'>head | tail<endfold id='3'>]</endfold id='3'> = <beginfold id='3'>[</beginfold id='3'>1,2,3<endfold id='3'>]</endfold id='3'>
head #=> 1
tail #=> [2,3]

# In elixir, just like in Erlang, the `=` denotes pattern matching and
# not an assignment.
#
# This means that the left-hand side (pattern) is matched against a
# right-hand side.
#
# This is how the above example of accessing the head and tail of a list works.

# A pattern match will error when the sides don't match, in this example
# the tuples have different sizes.
# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}

# There are also binaries
<beginfold id='4'><<</beginfold id='4'>1,2,3<endfold id='4'>>></endfold id='4'> # binary

# Strings and char lists
"hello" # string
'hello' # char list

# Multi-line strings
"""
I'm a multi-line
string.
"""
#=> "I'm a multi-line\nstring.\n"

# Strings are all encoded in UTF-8:
"héllò" #=> "héllò"

# Strings are really just binaries, and char lists are just lists.
<beginfold id='4'><<</beginfold id='4'>?a, ?b, ?c<endfold id='4'>>></endfold id='4'> #=> "abc"
<beginfold id='3'>[</beginfold id='3'>?a, ?b, ?c<endfold id='3'>]</endfold id='3'>   #=> 'abc'

# `?a` in elixir returns the ASCII integer for the letter `a`
?a #=> 97

# To concatenate lists use `++`, for binaries use `<>`
<beginfold id='3'>[</beginfold id='3'>1,2,3<endfold id='3'>]</endfold id='3'> ++ <beginfold id='3'>[</beginfold id='3'>4,5<endfold id='3'>]</endfold id='3'>     #=> [1,2,3,4,5]
'hello ' ++ 'world'  #=> 'hello world'

<beginfold id='4'><<</beginfold id='4'>1,2,3<endfold id='4'>>></endfold id='4'> <> <beginfold id='4'><<</beginfold id='4'>4,5<endfold id='4'>>></endfold id='4'> #=> <<1,2,3,4,5>>
"hello " <> "world"  #=> "hello world"

# Ranges are represented as `start..end` (both inclusive)
1..10 #=> 1..10
lower..upper = 1..10 # Can use pattern matching on ranges as well
<beginfold id='3'>[</beginfold id='3'>lower, upper<endfold id='3'>]</endfold id='3'> #=> [1, 10]

## ---------------------------
## -- Operators
## ---------------------------

# Some math
1 + 1  #=> 2
10 - 5 #=> 5
5 * 2  #=> 10
10 / 2 #=> 5.0

# In elixir the operator `/` always returns a float.

# To do integer division use `div`
div<beginfold id='2'>(</beginfold id='2'>10, 2<endfold id='2'>)</endfold id='2'> #=> 5

# To get the division remainder use `rem`
rem<beginfold id='2'>(</beginfold id='2'>10, 3<endfold id='2'>)</endfold id='2'> #=> 1

# There are also boolean operators: `or`, `and` and `not`.
# These operators expect a boolean as their first argument.
true and true #=> true
false or true #=> true
# 1 and true    #=> ** (ArgumentError) argument error

# Elixir also provides `||`, `&&` and `!` which accept arguments of any type.
# All values except `false` and `nil` will evaluate to true.
1 || true  #=> 1
false && 1 #=> false
nil && 20  #=> nil
!true #=> false

# For comparisons we have: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>`
1 == 1 #=> true
1 != 1 #=> false
1 < 2  #=> true

# `===` and `!==` are more strict when comparing integers and floats:
1 == 1.0  #=> true
1 === 1.0 #=> false

# We can also compare two different data types:
1 < :hello #=> true

# The overall sorting order is defined below:
# number < atom < reference < functions < port < pid < tuple < list < bit string

# To quote Joe Armstrong on this: "The actual order is not important,
# but that a total ordering is well defined is important."

## ---------------------------
## -- Control Flow
## ---------------------------

# `if` expression
if false <beginfold id='5'>do</beginfold id='5'>
  "This will never be seen"
else
  "This will"
<endfold id='5'>end</endfold id='5'>

# There's also `unless`
unless true <beginfold id='5'>do</beginfold id='5'>
  "This will never be seen"
else
  "This will"
<endfold id='5'>end</endfold id='5'>

# Remember pattern matching? Many control-flow structures in elixir rely on it.

# `case` allows us to compare a value against many patterns:
case <beginfold id='1'>{</beginfold id='1'>:one, :two<endfold id='1'>}</endfold id='1'> <beginfold id='5'>do</beginfold id='5'>
  <beginfold id='1'>{</beginfold id='1'>:four, :five<endfold id='1'>}</endfold id='1'> ->
    "This won't match"
  <beginfold id='1'>{</beginfold id='1'>:one, x<endfold id='1'>}</endfold id='1'> ->
    "This will match and bind `x` to `:two`"
  _ ->
    "This will match any value"
<endfold id='5'>end</endfold id='5'>

# It's common to bind the value to `_` if we don't need it.
# For example, if only the head of a list matters to us:
<beginfold id='3'>[</beginfold id='3'>head | _<endfold id='3'>]</endfold id='3'> = <beginfold id='3'>[</beginfold id='3'>1,2,3<endfold id='3'>]</endfold id='3'>
head #=> 1

# For better readability we can do the following:
<beginfold id='3'>[</beginfold id='3'>head | _tail<endfold id='3'>]</endfold id='3'> = <beginfold id='3'>[</beginfold id='3'>:a, :b, :c<endfold id='3'>]</endfold id='3'>
head #=> :a

# `cond` lets us check for many conditions at the same time.
# Use `cond` instead of nesting many `if` expressions.
cond <beginfold id='5'>do</beginfold id='5'>
  1 + 1 == 3 ->
    "I will never be seen"
  2 * 5 == 12 ->
    "Me neither"
  1 + 2 == 3 ->
    "But I will"
<endfold id='5'>end</endfold id='5'>

# It is common to set the last condition equal to `true`, which will always match.
cond <beginfold id='5'>do</beginfold id='5'>
  1 + 1 == 3 ->
    "I will never be seen"
  2 * 5 == 12 ->
    "Me neither"
  true ->
    "But I will (this is essentially an else)"
<endfold id='5'>end</endfold id='5'>

# `try/catch` is used to catch values that are thrown, it also supports an
# `after` clause that is invoked whether or not a value is caught.
try <beginfold id='5'>do</beginfold id='5'>
  throw<beginfold id='2'>(</beginfold id='2'>:hello<endfold id='2'>)</endfold id='2'>
catch
  message -> "Got #{message}."
after
  IO.puts<beginfold id='2'>(</beginfold id='2'>"I'm the after clause."<endfold id='2'>)</endfold id='2'>
<endfold id='5'>end</endfold id='5'>
#=> I'm the after clause
# "Got :hello"

## ---------------------------
## -- Modules and Functions
## ---------------------------

# Anonymous functions (notice the dot)
square = fn<beginfold id='2'>(</beginfold id='2'>x<endfold id='2'>)</endfold id='2'> -> x * x <endfold id='5'>end</endfold id='5'>
square.<beginfold id='2'>(</beginfold id='2'>5<endfold id='2'>)</endfold id='2'> #=> 25

# They also accept many clauses and guards.
# Guards let you fine tune pattern matching,
# they are indicated by the `when` keyword:
f = <beginfold id='5'>fn</beginfold id='5'>
  x, y when x > 0 -> x + y
  x, y -> x * y
<endfold id='5'>end</endfold id='5'>

f.<beginfold id='2'>(</beginfold id='2'>1, 3<endfold id='2'>)</endfold id='2'>  #=> 4
f.<beginfold id='2'>(</beginfold id='2'>-1, 3<endfold id='2'>)</endfold id='2'> #=> -3

# Elixir also provides many built-in functions.
# These are available in the current scope.
is_number<beginfold id='2'>(</beginfold id='2'>10<endfold id='2'>)</endfold id='2'>    #=> true
is_list<beginfold id='2'>(</beginfold id='2'>"hello"<endfold id='2'>)</endfold id='2'> #=> false
elem<beginfold id='2'>(</beginfold id='2'><beginfold id='1'>{</beginfold id='1'>1,2,3<endfold id='1'>}</endfold id='1'>, 0<endfold id='2'>)</endfold id='2'> #=> 1

# You can group several functions into a module. Inside a module use `def`
# to define your functions.
defmodule Math <beginfold id='5'>do</beginfold id='5'>
  def sum<beginfold id='2'>(</beginfold id='2'>a, b<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    a + b
  <endfold id='5'>end</endfold id='5'>

  def square<beginfold id='2'>(</beginfold id='2'>x<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    x * x
  <endfold id='5'>end</endfold id='5'>
<endfold id='5'>end</endfold id='5'>

Math.sum<beginfold id='2'>(</beginfold id='2'>1, 2<endfold id='2'>)</endfold id='2'>  #=> 3
Math.square<beginfold id='2'>(</beginfold id='2'>3<endfold id='2'>)</endfold id='2'> #=> 9

# To compile our simple Math module save it as `math.ex` and use `elixirc`
# in your terminal: elixirc math.ex

# Inside a module we can define functions with `def` and private functions with `defp`.
# A function defined with `def` is available to be invoked from other modules,
# a private function can only be invoked locally.
defmodule PrivateMath <beginfold id='5'>do</beginfold id='5'>
  def sum<beginfold id='2'>(</beginfold id='2'>a, b<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    do_sum<beginfold id='2'>(</beginfold id='2'>a, b<endfold id='2'>)</endfold id='2'>
  <endfold id='5'>end</endfold id='5'>

  defp do_sum<beginfold id='2'>(</beginfold id='2'>a, b<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    a + b
  <endfold id='5'>end</endfold id='5'>
<endfold id='5'>end</endfold id='5'>

PrivateMath.sum<beginfold id='2'>(</beginfold id='2'>1, 2<endfold id='2'>)</endfold id='2'>    #=> 3
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)

# Function declarations also support guards and multiple clauses:
defmodule Geometry <beginfold id='5'>do</beginfold id='5'>
  def area<beginfold id='2'>(</beginfold id='2'><beginfold id='1'>{</beginfold id='1'>:rectangle, w, h<endfold id='1'>}</endfold id='1'><endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    w * h
  <endfold id='5'>end</endfold id='5'>

  def area<beginfold id='2'>(</beginfold id='2'><beginfold id='1'>{</beginfold id='1'>:circle, r<endfold id='1'>}</endfold id='1'><endfold id='2'>)</endfold id='2'> when is_number<beginfold id='2'>(</beginfold id='2'>r<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    3.14 * r * r
  <endfold id='5'>end</endfold id='5'>
<endfold id='5'>end</endfold id='5'>

Geometry.area<beginfold id='2'>(</beginfold id='2'><beginfold id='1'>{</beginfold id='1'>:rectangle, 2, 3<endfold id='1'>}</endfold id='1'><endfold id='2'>)</endfold id='2'> #=> 6
Geometry.area<beginfold id='2'>(</beginfold id='2'><beginfold id='1'>{</beginfold id='1'>:circle, 3<endfold id='1'>}</endfold id='1'><endfold id='2'>)</endfold id='2'>       #=> 28.25999999999999801048
# Geometry.area({:circle, "not_a_number"})
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1

# Due to immutability, recursion is a big part of elixir
defmodule Recursion <beginfold id='5'>do</beginfold id='5'>
  def sum_list<beginfold id='2'>(</beginfold id='2'><beginfold id='3'>[</beginfold id='3'>head | tail<endfold id='3'>]</endfold id='3'>, acc<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    sum_list<beginfold id='2'>(</beginfold id='2'>tail, acc + head<endfold id='2'>)</endfold id='2'>
  <endfold id='5'>end</endfold id='5'>

  def sum_list<beginfold id='2'>(</beginfold id='2'><beginfold id='3'>[</beginfold id='3'><endfold id='3'>]</endfold id='3'>, acc<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
    acc
  <endfold id='5'>end</endfold id='5'>
<endfold id='5'>end</endfold id='5'>

Recursion.sum_list<beginfold id='2'>(</beginfold id='2'><beginfold id='3'>[</beginfold id='3'>1,2,3<endfold id='3'>]</endfold id='3'>, 0<endfold id='2'>)</endfold id='2'> #=> 6

# Elixir modules support attributes, there are built-in attributes and you
# may also add custom ones.
defmodule MyMod <beginfold id='5'>do</beginfold id='5'>
  <beginfold id='6'>@moduledoc """</beginfold id='6'>
  This is a built-in attribute on a example module.
  <endfold id='6'>"""</endfold id='6'>

  @my_data 100 # This is a custom attribute.
  IO.inspect<beginfold id='2'>(</beginfold id='2'>@my_data<endfold id='2'>)</endfold id='2'> #=> 100
<endfold id='5'>end</endfold id='5'>

## ---------------------------
## -- Structs and Exceptions
## ---------------------------

# Structs are extensions on top of maps that bring default values,
# compile-time guarantees and polymorphism into Elixir.
defmodule Person <beginfold id='5'>do</beginfold id='5'>
  defstruct name: nil, age: 0, height: 0
<endfold id='5'>end</endfold id='5'>

joe_info = %Person<beginfold id='1'>{</beginfold id='1'> name: "Joe", age: 30, height: 180 <endfold id='1'>}</endfold id='1'>
#=> %Person{age: 30, height: 180, name: "Joe"}

# Access the value of name
joe_info.name #=> "Joe"

# Update the value of age
older_joe_info = %<beginfold id='1'>{</beginfold id='1'> joe_info | age: 31 <endfold id='1'>}</endfold id='1'>
#=> %Person{age: 31, height: 180, name: "Joe"}

# The `try` block with the `rescue` keyword is used to handle exceptions
try <beginfold id='5'>do</beginfold id='5'>
  raise "some error"
rescue
  RuntimeError -> "rescued a runtime error"
  _error -> "this will rescue any error"
<endfold id='5'>end</endfold id='5'>
#=> "rescued a runtime error"

# All exceptions have a message
try <beginfold id='5'>do</beginfold id='5'>
  raise "some error"
rescue
  x in <beginfold id='3'>[</beginfold id='3'>RuntimeError<endfold id='3'>]</endfold id='3'> ->
    x.message
<endfold id='5'>end</endfold id='5'>
#=> "some error"

## ---------------------------
## -- Concurrency
## ---------------------------

# Elixir relies on the actor model for concurrency. All we need to write
# concurrent programs in elixir are three primitives: spawning processes,
# sending messages and receiving messages.

# To start a new process we use the `spawn` function, which takes a function
# as argument.
f = <beginfold id='5'>fn</beginfold id='5'> -> 2 * 2 <endfold id='5'>end</endfold id='5'> #=> #Function<erl_eval.20.80484245>
spawn<beginfold id='2'>(</beginfold id='2'>f<endfold id='2'>)</endfold id='2'> #=> #PID<0.40.0>

# `spawn` returns a pid (process identifier), you can use this pid to send
# messages to the process. To do message passing we use the `send` operator.
# For all of this to be useful we need to be able to receive messages. This is
# achieved with the `receive` mechanism:

# The `receive do` block is used to listen for messages and process
# them when they are received. A `receive do` block will only
# process one received message. In order to process multiple
# messages, a function with a `receive do` block must recursively
# call itself to get into the `receive do` block again.

defmodule Geometry <beginfold id='5'>do</beginfold id='5'>
  def area_loop <beginfold id='5'>do</beginfold id='5'>
    receive <beginfold id='5'>do</beginfold id='5'>
      <beginfold id='1'>{</beginfold id='1'>:rectangle, w, h<endfold id='1'>}</endfold id='1'> ->
        IO.puts<beginfold id='2'>(</beginfold id='2'>"Area = #{w * h}"<endfold id='2'>)</endfold id='2'>
        area_loop<beginfold id='2'>(</beginfold id='2'><endfold id='2'>)</endfold id='2'>
      <beginfold id='1'>{</beginfold id='1'>:circle, r<endfold id='1'>}</endfold id='1'> ->
        IO.puts<beginfold id='2'>(</beginfold id='2'>"Area = #{3.14 * r * r}"<endfold id='2'>)</endfold id='2'>
        area_loop<beginfold id='2'>(</beginfold id='2'><endfold id='2'>)</endfold id='2'>
    <endfold id='5'>end</endfold id='5'>
  <endfold id='5'>end</endfold id='5'>
<endfold id='5'>end</endfold id='5'>

# Compile the module and create a process that evaluates `area_loop` in the shell
pid = spawn<beginfold id='2'>(</beginfold id='2'><beginfold id='5'>fn</beginfold id='5'> -> Geometry.area_loop<beginfold id='2'>(</beginfold id='2'><endfold id='2'>)</endfold id='2'> <endfold id='5'>end</endfold id='5'><endfold id='2'>)</endfold id='2'> #=> #PID<0.40.0>
# Alternatively
pid = spawn<beginfold id='2'>(</beginfold id='2'>Geometry, :area_loop, <beginfold id='3'>[</beginfold id='3'><endfold id='3'>]</endfold id='3'><endfold id='2'>)</endfold id='2'>

# Send a message to `pid` that will match a pattern in the receive statement
send pid, <beginfold id='1'>{</beginfold id='1'>:rectangle, 2, 3<endfold id='1'>}</endfold id='1'>
#=> Area = 6
#   {:rectangle,2,3}

send pid, <beginfold id='1'>{</beginfold id='1'>:circle, 2<endfold id='1'>}</endfold id='1'>
#=> Area = 12.56000000000000049738
#   {:circle,2}

# The shell is also a process, you can use `self` to get the current pid
self<beginfold id='2'>(</beginfold id='2'><endfold id='2'>)</endfold id='2'> #=> #PID<0.27.0>

# Code not found in the original, but needed to test the full range of the syntax

def function, do: <beginfold id='1'>{</beginfold id='1'>:ok, result<endfold id='1'>}</endfold id='1'>

<beginfold id='3'>[</beginfold id='3'>
  :a,
  :b,
  :c
<endfold id='3'>]</endfold id='3'>

%<beginfold id='1'>{</beginfold id='1'>
  a: "a",
  b: "b",
  c: "c"
<endfold id='1'>}</endfold id='1'>

%A<beginfold id='1'>{</beginfold id='1'>
  a: "a",
  b: "b",
  c: "c"
<endfold id='1'>}</endfold id='1'>

# Numerics
0xBE_EF
0o777_1
0b1010_0101_01
01234
1234_5678_9

3.14_159
1_23.00_00
4.13e20
6.12e-8


"String Interpolation: #{inspect<beginfold id='2'>(</beginfold id='2'>nil<endfold id='2'>)</endfold id='2'>}"

# Sigils
~r<beginfold id='7'>/</beginfold id='7'>\bfoo_bar\b<endfold id='7'>/</endfold id='7'>g
~s<beginfold id='7'>"</beginfold id='7'>asdf<endfold id='7'>"</endfold id='7'>
~w<beginfold id='7'>[</beginfold id='7'>foo bar one two three<endfold id='7'>]</endfold id='7'>a
~w<beginfold id='7'>(</beginfold id='7'>foo bar one two three<endfold id='7'>)</endfold id='7'>a

~c<beginfold id='7'>'</beginfold id='7'>char lists are typed like this now<endfold id='7'>'</endfold id='7'>

# Documentation
<beginfold id='6'>@doc """</beginfold id='6'>
## Documentation
lorem ipsum dolor

* a
* b
* c

1. x
2. y
3. z
<endfold id='6'>"""</endfold id='6'>

# Module Attributes
@compile <beginfold id='1'>{</beginfold id='1'>:inline, foo: 1<endfold id='1'>}</endfold id='1'>
@custom_attribute <beginfold id='3'>[</beginfold id='3'>1, 2, 3, 4<endfold id='3'>]</endfold id='3'>

# More Atoms
:"@foo"
:bar?
:bar!
%<beginfold id='1'>{</beginfold id='1'>
  foo?: false,
  "@bar": 1
<endfold id='1'>}</endfold id='1'>
:+
:**
:++
:%{}

# Interpolation in Atoms
:"bar#{inspect<beginfold id='2'>(</beginfold id='2'>foo<beginfold id='2'>(</beginfold id='2'><endfold id='2'>)</endfold id='2'><endfold id='2'>)</endfold id='2'>}"

# Character Literals
<beginfold id='3'>[</beginfold id='3'>?a, ?b, ?c, ?z, ?1, ?-, ?+, ?., ?\s, ?\n<endfold id='3'>]</endfold id='3'>

# Special Forms
def foo<beginfold id='2'>(</beginfold id='2'>_, _opts<endfold id='2'>)</endfold id='2'> <beginfold id='5'>do</beginfold id='5'>
  IO.inspect<beginfold id='2'>(</beginfold id='2'>__MODULE__<endfold id='2'>)</endfold id='2'>
  %__MODULE__<beginfold id='1'>{</beginfold id='1'><endfold id='1'>}</endfold id='1'>
<endfold id='5'>end</endfold id='5'>