From a86c8fe2c959b4ada383c748e4aae1525b8bf7c3 Mon Sep 17 00:00:00 2001 From: mrshankly Date: Tue, 2 Jul 2013 12:07:34 +0100 Subject: [PATCH] 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