From a86c8fe2c959b4ada383c748e4aae1525b8bf7c3 Mon Sep 17 00:00:00 2001 From: mrshankly Date: Tue, 2 Jul 2013 12:07:34 +0100 Subject: Added first draft for elixir. --- elixir.html.markdown | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 elixir.html.markdown diff --git a/elixir.html.markdown b/elixir.html.markdown new file mode 100644 index 00000000..9343a683 --- /dev/null +++ b/elixir.html.markdown @@ -0,0 +1,204 @@ +--- +language: elixir +author: Joao Marques +author_url: http://github.com/mrshankly +filename: learnelixir.ex +--- + +```elixir +# Single line comments start with a hash. + +## -------------------- +## -- 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 contigously in memory. +{1,2,3} # tuple + +# We can access a tuple element with the `elem` function: +elem({1, 2, 3}, 0) # => 1 + +# Lists that are implemented as linked lists. +[1,2,3] # list + +# We can access the head and tail of a list as follows: +[head | tail] = [1,2,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's also binaries +<<1,2,3>> # binary + +# Strings and char lists +"hello" # string +'hello' # char list + +# Strings are all encoded in UTF-8: +"héllò" # => "héllò" + +# Strings are really just binaries, and char lists are just lists. +<> # => "abc" +[?a, ?b, ?c] # => 'abc' + +# `?a` in elixir returns the ASCII integer for the letter `a` +?a # => 97 + +## TODO: +###################################################### +## JOIN BINARIES AND LISTS +###################################################### + +## -------------------- +## -- 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(10, 2) # => 5 + +# To get the division remainder use `rem` +rem(10, 3) # => 1 + +# There's 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 do + "This will never be seen" +else + "This will" +end + +# There's also `unless` +unless true do + "This will never be seen" +else + "This will" +end + +# Remember pattern matching? Many control-flow structures in elixir rely on it. + +# `case` allows us to compare a value against many patterns: +case {:one, :two} do + {:four, :five} -> + "This won't match" + {:one, x} -> + "This will match and assign `x` to `:two`" + _ -> + "This will match any value" +end + +# It's common practive to assign a value to `_` if we don't need it. +# For example, if only the head of a list matters to us: +[head | _] = [1,2,3] +head # => 1 + +# For better readability we can do the following: +[head | _tail] = [:a, :b, :c] +head # => :a + +# `cond` lets us check for many conditions at the same time. +# Use `cond` instead of nesting many `if` expressions. +cond do + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + 1 + 2 == 3 -> + "But I will" +end + +# It is common to see a last condition equal to `true`, which will always match. +cond do + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + true -> + "But I will (this is essentially an else)" +end + +# `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 catched. +try do + throw(:hello) +catch + message -> "Got #{message}." +after + IO.puts("I'm the after clause.") +end +# => I'm the after clause +# "Got :hello" + +## TODO: +###################################################### +## GUARDS +###################################################### + +## --------------------------- +## -- Modules and Functions +## --------------------------- + + + +``` \ No newline at end of file -- cgit v1.2.3 From f68a80312b4bf56fd14b5f03d4644688d26710a0 Mon Sep 17 00:00:00 2001 From: mrshankly Date: Tue, 2 Jul 2013 13:16:12 +0100 Subject: Added section about functions, modules and records. --- elixir.html.markdown | 116 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 5 deletions(-) diff --git a/elixir.html.markdown b/elixir.html.markdown index 9343a683..a37d0f5e 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -68,9 +68,9 @@ tail # => [2,3] ## JOIN BINARIES AND LISTS ###################################################### -## -------------------- +## --------------------------- ## -- Operators -## -------------------- +## --------------------------- # Some math 1 + 1 # => 2 @@ -118,9 +118,9 @@ 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 do @@ -199,6 +199,112 @@ end ## -- Modules and Functions ## --------------------------- +############################### +## EXPLAIN built-in functions? +############################### + +# Anonymous functions (notice the dot) +square = fn(x) -> x * x end +square.(5) #=> 25 + +# They also accept many clauses and guards +f = fn + x, y when x > 0 -> x + y + x, y -> x * y +end + +f.(1, 3) #=> 4 +f.(-1, 3) #=> -3 + +# You can group several functions into a module. Inside a module use `def` +# to define your functions. +defmodule Math do + def sum(a, b) do + a + b + end + + def square(x) do + x * x + end +end + +Math.sum(1, 2) #=> 3 +Match.square(3) #=> 9 + +# To compile our little Math module save it as `math.ex` and use `elixirc` +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 do + def sum(a, b) do + do_sum(a, b) + end + + defp do_sum(a, b) do + a + b + end +end + +PrivateMath.sum(1, 2) #=> 3 +PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError) + +# Function declarations also support guards and multiple clauses: +defmodule Geometry do + def area({:rectangle, w, h}) do + w * h + end + + def area({:circle, r}) when r > 0 do + 3.14 * r * r + end +end + +Geometry.area({:rectangle, 2, 3}) #=> 6 +Geometry.area({:circle, 3}) #=> 28.25999999999999801048 + +# Due to immutability, recursion is a big part of elixir +defmodule Recursion do + def sum_list([head | tail], acc) do + sum_list(tail, acc + head) + end + + def sum_list([], acc) do + acc + end +end + +Recursion.sum_list([1,2,3], 0) #=> 6 + +############################### +## EXPLAIN module attributes +############################### + +## --------------------------- +## -- Records and Exceptions +## --------------------------- + +# Records are basically structures that allow you to associate a name with +# a particular value. +defrecord Person, name: nil, age: 0, height: 0 + +joe_info = Person.new(name: "Joe", age: 30, height: 180) +#=> Person[name: "Joe", age: 30, height: 180] +# Access the value of name +joe_info.name #=> "Joe" + +# Update the value of age +joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] + +## TODO: Exceptions + +## --------------------------- +## -- Concurrency +## --------------------------- -``` \ No newline at end of file +## TODO +``` -- cgit v1.2.3 From 6763fc89e314b9b6b43cc4e2a38d4d7fdacfa2d4 Mon Sep 17 00:00:00 2001 From: mrshankly Date: Tue, 2 Jul 2013 23:23:49 +0100 Subject: Finished first draft of learnelixir. --- elixir.html.markdown | 179 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 125 insertions(+), 54 deletions(-) diff --git a/elixir.html.markdown b/elixir.html.markdown index a37d0f5e..11a0701c 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -24,15 +24,15 @@ filename: learnelixir.ex {1,2,3} # tuple # We can access a tuple element with the `elem` function: -elem({1, 2, 3}, 0) # => 1 +elem({1, 2, 3}, 0) #=> 1 # Lists that are implemented as linked lists. [1,2,3] # list # We can access the head and tail of a list as follows: [head | tail] = [1,2,3] -head # => 1 -tail # => [2,3] +head #=> 1 +tail #=> [2,3] # In elixir, just like in erlang, the `=` denotes pattern matching and # not an assignment. @@ -44,7 +44,7 @@ tail # => [2,3] # 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} +{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2} # There's also binaries <<1,2,3>> # binary @@ -53,64 +53,73 @@ tail # => [2,3] "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ò" +"héllò" #=> "héllò" # Strings are really just binaries, and char lists are just lists. -<> # => "abc" -[?a, ?b, ?c] # => 'abc' +<> #=> "abc" +[?a, ?b, ?c] #=> 'abc' # `?a` in elixir returns the ASCII integer for the letter `a` -?a # => 97 +?a #=> 97 + +# To concatenate lists use `++`, for binaries use `<>` +[1,2,3] ++ [4,5] #=> [1,2,3,4,5] +'hello ' ++ 'world' #=> 'hello world' -## TODO: -###################################################### -## JOIN BINARIES AND LISTS -###################################################### +<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>> +"hello " <> "world" #=> "hello world" ## --------------------------- ## -- Operators ## --------------------------- # Some math -1 + 1 # => 2 -10 - 5 # => 5 -5 * 2 # => 10 -10 / 2 # => 5.0 +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(10, 2) # => 5 +div(10, 2) #=> 5 # To get the division remainder use `rem` -rem(10, 3) # => 1 +rem(10, 3) #=> 1 # There's 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 +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 +1 || true #=> 1 +false && 1 #=> false +nil && 20 #=> nil -!true # => false +!true #=> false # For comparisons we have: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>` -1 == 1 # => true -1 != 1 # => false -1 < 2 # => true +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 +1 == 1.0 #=> true +1 === 1.0 #=> false # We can also compare two different data types: -1 < :hello # => true +1 < :hello #=> true # The overall sorting order is defined below: number < atom < reference < functions < port < pid < tuple < list < bit string @@ -151,11 +160,11 @@ end # It's common practive to assign a value to `_` if we don't need it. # For example, if only the head of a list matters to us: [head | _] = [1,2,3] -head # => 1 +head #=> 1 # For better readability we can do the following: [head | _tail] = [:a, :b, :c] -head # => :a +head #=> :a # `cond` lets us check for many conditions at the same time. # Use `cond` instead of nesting many `if` expressions. @@ -187,27 +196,19 @@ catch after IO.puts("I'm the after clause.") end -# => I'm the after clause -# "Got :hello" - -## TODO: -###################################################### -## GUARDS -###################################################### +#=> I'm the after clause +# "Got :hello" ## --------------------------- ## -- Modules and Functions ## --------------------------- -############################### -## EXPLAIN built-in functions? -############################### - # Anonymous functions (notice the dot) square = fn(x) -> x * x end square.(5) #=> 25 -# They also accept many clauses and guards +# They also accept many clauses and guards. Guards let you fine tune pattern matching, +# they are indicated by the `when` keyword: f = fn x, y when x > 0 -> x + y x, y -> x * y @@ -216,6 +217,12 @@ end f.(1, 3) #=> 4 f.(-1, 3) #=> -3 +# Elixir also provides many built-in functions. +# These are available in the current scope. +is_number(10) #=> true +is_list("hello") #=> false +elem({1,2,3}, 0) #=> 1 + # You can group several functions into a module. Inside a module use `def` # to define your functions. defmodule Math do @@ -234,9 +241,7 @@ Match.square(3) #=> 9 # To compile our little Math module save it as `math.ex` and use `elixirc` elixirc math.ex -# Inside a module we can define functions with `def` and -# private functions with `defp`. -# +# 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 do @@ -258,7 +263,7 @@ defmodule Geometry do w * h end - def area({:circle, r}) when r > 0 do + def area({:circle, r}) when is_number(r) do 3.14 * r * r end end @@ -279,9 +284,17 @@ end Recursion.sum_list([1,2,3], 0) #=> 6 -############################### -## EXPLAIN module attributes -############################### +# Elixir modules support attributes, there are built-in attributes and you +# may also add custom attributes. + +defmodule MyMod do + @moduledoc """ + This is a built-in attribute on a example module. + """ + + @my_data 100 # This is a custom attribute. + IO.inspect(@my_data) #=> 100 +end ## --------------------------- ## -- Records and Exceptions @@ -300,11 +313,69 @@ joe_info.name #=> "Joe" # Update the value of age joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] -## TODO: Exceptions +# The `try` block with the `rescue` keyword is used to handle exceptions +try do + raise "some error" +rescue + RuntimeError -> "rescued a runtime error" + _error -> "this will rescue any error" +end + +# All exceptions have a message +try do + raise "some error" +rescue + x in [RuntimeError] -> + x.message +end ## --------------------------- ## -- Concurrency ## --------------------------- -## TODO +# 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 = fn -> 2 * 2 end #=> #Function +spawn(f) #=> #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 `<-` operator. +# For all of this to be useful we need to be able to receive messages. This is +# achived with the `receive` mechanism: + +defmodule Geometry do + def area_loop do + receive do + {:rectangle, w, h} -> + IO.puts("Area = #{w * h}") + area_loop() + {:circle, r} -> + IO.puts("Area = #{3.14 * r * r}") + area_loop() + end + end +end + +# Compile the module and create a process that evaluates `area_loop` in the shell +pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0> + +# Send a message to `pid` that will match a pattern in the receive statement +pid <- {:rectangle, 2, 3} +#=> Area = 6 +# {:rectangle,2,3} + +pid <- {:circle, 2} +#=> Area = 12.56000000000000049738 +# {:circle,2} ``` + +## References + +* [Getting started guide](http://elixir-lang.org/getting_started/1.html) from [elixir webpage](http://elixir-lang.org) +* [Elixir Documentation](http://elixir-lang.org/docs/master/) +* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert +* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong \ No newline at end of file -- cgit v1.2.3 From 231a211ef213142bd856356924102f9a25d55e83 Mon Sep 17 00:00:00 2001 From: mrshankly Date: Tue, 2 Jul 2013 23:37:18 +0100 Subject: Added some info about how to run the shell and compile modules. --- elixir.html.markdown | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/elixir.html.markdown b/elixir.html.markdown index 11a0701c..255d311d 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -6,11 +6,19 @@ filename: learnelixir.ex --- ```elixir -# Single line comments start with a hash. +# Single line comments start with a hashtag. -## -------------------- +# 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 @@ -286,7 +294,6 @@ Recursion.sum_list([1,2,3], 0) #=> 6 # Elixir modules support attributes, there are built-in attributes and you # may also add custom attributes. - defmodule MyMod do @moduledoc """ This is a built-in attribute on a example module. @@ -346,7 +353,6 @@ spawn(f) #=> #PID<0.40.0> # messages to the process. To do message passing we use the `<-` operator. # For all of this to be useful we need to be able to receive messages. This is # achived with the `receive` mechanism: - defmodule Geometry do def area_loop do receive do @@ -371,6 +377,9 @@ pid <- {:rectangle, 2, 3} pid <- {:circle, 2} #=> Area = 12.56000000000000049738 # {:circle,2} + +# The shell is also a process, you can use `self` to get the current pid +self() #=> #PID<0.27.0> ``` ## References -- cgit v1.2.3 From a136cfe86a3c28ac16c2aa4a3323413cfd76c46f Mon Sep 17 00:00:00 2001 From: mrshankly Date: Wed, 3 Jul 2013 00:03:44 +0100 Subject: Added one more example with guards, fixed typos and identation. --- elixir.html.markdown | 154 ++++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/elixir.html.markdown b/elixir.html.markdown index 255d311d..0ded7562 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -141,33 +141,33 @@ number < atom < reference < functions < port < pid < tuple < list < bit string # `if` expression if false do - "This will never be seen" + "This will never be seen" else - "This will" + "This will" end # There's also `unless` unless true do - "This will never be seen" + "This will never be seen" else - "This will" + "This will" end # Remember pattern matching? Many control-flow structures in elixir rely on it. # `case` allows us to compare a value against many patterns: case {:one, :two} do - {:four, :five} -> - "This won't match" - {:one, x} -> - "This will match and assign `x` to `:two`" - _ -> - "This will match any value" + {:four, :five} -> + "This won't match" + {:one, x} -> + "This will match and assign `x` to `:two`" + _ -> + "This will match any value" end # It's common practive to assign a value to `_` if we don't need it. # For example, if only the head of a list matters to us: -[head | _] = [1,2,3] +[head | _] = [1,2,3] head #=> 1 # For better readability we can do the following: @@ -177,35 +177,35 @@ head #=> :a # `cond` lets us check for many conditions at the same time. # Use `cond` instead of nesting many `if` expressions. cond do - 1 + 1 == 3 -> - "I will never be seen" - 2 * 5 == 12 -> - "Me neither" - 1 + 2 == 3 -> - "But I will" + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + 1 + 2 == 3 -> + "But I will" end # It is common to see a last condition equal to `true`, which will always match. cond do - 1 + 1 == 3 -> - "I will never be seen" - 2 * 5 == 12 -> - "Me neither" - true -> - "But I will (this is essentially an else)" + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + true -> + "But I will (this is essentially an else)" end # `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 catched. try do - throw(:hello) + throw(:hello) catch - message -> "Got #{message}." + message -> "Got #{message}." after - IO.puts("I'm the after clause.") + IO.puts("I'm the after clause.") end #=> I'm the after clause -# "Got :hello" +# "Got :hello" ## --------------------------- ## -- Modules and Functions @@ -218,8 +218,8 @@ square.(5) #=> 25 # They also accept many clauses and guards. Guards let you fine tune pattern matching, # they are indicated by the `when` keyword: f = fn - x, y when x > 0 -> x + y - x, y -> x * y + x, y when x > 0 -> x + y + x, y -> x * y end f.(1, 3) #=> 4 @@ -234,32 +234,32 @@ elem({1,2,3}, 0) #=> 1 # You can group several functions into a module. Inside a module use `def` # to define your functions. defmodule Math do - def sum(a, b) do - a + b - end + def sum(a, b) do + a + b + end - def square(x) do - x * x - end + def square(x) do + x * x + end end Math.sum(1, 2) #=> 3 Match.square(3) #=> 9 -# To compile our little Math module save it as `math.ex` and use `elixirc` -elixirc math.ex +# 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 do - def sum(a, b) do - do_sum(a, b) - end + def sum(a, b) do + do_sum(a, b) + end - defp do_sum(a, b) do - a + b - end + defp do_sum(a, b) do + a + b + end end PrivateMath.sum(1, 2) #=> 3 @@ -267,27 +267,29 @@ PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError) # Function declarations also support guards and multiple clauses: defmodule Geometry do - def area({:rectangle, w, h}) do - w * h - end + def area({:rectangle, w, h}) do + w * h + end - def area({:circle, r}) when is_number(r) do - 3.14 * r * r - end + def area({:circle, r}) when is_number(r) do + 3.14 * r * r + end end Geometry.area({:rectangle, 2, 3}) #=> 6 Geometry.area({:circle, 3}) #=> 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 do - def sum_list([head | tail], acc) do - sum_list(tail, acc + head) - end + def sum_list([head | tail], acc) do + sum_list(tail, acc + head) + end - def sum_list([], acc) do - acc - end + def sum_list([], acc) do + acc + end end Recursion.sum_list([1,2,3], 0) #=> 6 @@ -295,12 +297,12 @@ Recursion.sum_list([1,2,3], 0) #=> 6 # Elixir modules support attributes, there are built-in attributes and you # may also add custom attributes. defmodule MyMod do - @moduledoc """ - This is a built-in attribute on a example module. - """ + @moduledoc """ + This is a built-in attribute on a example module. + """ - @my_data 100 # This is a custom attribute. - IO.inspect(@my_data) #=> 100 + @my_data 100 # This is a custom attribute. + IO.inspect(@my_data) #=> 100 end ## --------------------------- @@ -322,18 +324,18 @@ joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] # The `try` block with the `rescue` keyword is used to handle exceptions try do - raise "some error" + raise "some error" rescue - RuntimeError -> "rescued a runtime error" - _error -> "this will rescue any error" + RuntimeError -> "rescued a runtime error" + _error -> "this will rescue any error" end # All exceptions have a message try do - raise "some error" + raise "some error" rescue - x in [RuntimeError] -> - x.message + x in [RuntimeError] -> + x.message end ## --------------------------- @@ -354,16 +356,16 @@ spawn(f) #=> #PID<0.40.0> # For all of this to be useful we need to be able to receive messages. This is # achived with the `receive` mechanism: defmodule Geometry do - def area_loop do - receive do - {:rectangle, w, h} -> - IO.puts("Area = #{w * h}") - area_loop() - {:circle, r} -> - IO.puts("Area = #{3.14 * r * r}") - area_loop() - end - end + def area_loop do + receive do + {:rectangle, w, h} -> + IO.puts("Area = #{w * h}") + area_loop() + {:circle, r} -> + IO.puts("Area = #{3.14 * r * r}") + area_loop() + end + end end # Compile the module and create a process that evaluates `area_loop` in the shell -- cgit v1.2.3 From 78970bb8414e2ae956dae8720513eaf3024254f9 Mon Sep 17 00:00:00 2001 From: mrshankly Date: Wed, 3 Jul 2013 00:07:55 +0100 Subject: Added new line at the end of file. --- elixir.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elixir.html.markdown b/elixir.html.markdown index 0ded7562..c0544982 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -389,4 +389,4 @@ self() #=> #PID<0.27.0> * [Getting started guide](http://elixir-lang.org/getting_started/1.html) from [elixir webpage](http://elixir-lang.org) * [Elixir Documentation](http://elixir-lang.org/docs/master/) * ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert -* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong \ No newline at end of file +* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong -- cgit v1.2.3