mix new cardsto create a new projectjust sto enter iex shellrecompilein iex shell to recompile after changes
deck = new Deck(); // <Deck>
deck.cards; // [Card1, Card2, Card3, ...]
deck.shuffle(); // [Card2, Card1, Card3, ...]
deck.deal(); // Deck[Card2, Card3, ...]Number of arguments a funciton accepts is called its arity.
Immutable data structures are a core concept of functional programming. In Elixir, we have lists, tuples, maps, and structs. All of these data structures are immutable. This means that once they are created, they cannot be modified. Instead, any operation on an immutable data structure will return a new copy of that data structure with the modification applied.
-
Pattern Matching
-
Relationship to Erlang
Code written in Elixir is transpiled to Erlang bytecode, then is compiled and executed on the Erlang virtual machine (BEAM, conceptually similar to JVM). Elixir can be thought of as a more modern syntax for Erlang. Elixir also provides a lot of conveniences that Erlang does not, such as a package manager, a test framework, and a build tool.
-
Atoms: Atoms are constants where their name is their own value. They are often used to express state, such as
:okor:error, useful for pattern matching. They are also used to reference modules, such as:mathor:lists. -
Tests: Elixir comes with a built-in test framework called ExUnit. Tests are written in the test/ directory and are named with the _test.exs suffix. To run tests, use the
mix testcommand. Also contains documentation tests, which are tests that are run as part of the documentation generation process.
defmodule CardsTest do
use ExUnit.Case
# Setup is a special callback run before each test
setup do
deck = Cards.create_deck()
{:ok, deck: deck}
end
# context is the state returned from setup
test "create_deck/0", context do
assert length(context[:deck]) == 52
end
endMaps are key-value stores in Elixir. They are denoted by %{}.
# Creating a map
map = %{ "name" => "John", "age" => 30 }
# Accessing values
IO.puts(map["name"]) # Outputs: "John"
# Updating a map
map = Map.put(map, "age", 31)
IO.puts(map["age"]) # Outputs: 31
# Pattern matching with maps
%{"name" => name} = map
IO.puts(name) # Outputs: "John"Keyword lists are lists of tuples where the first element of the tuple is an atom. They are denoted by [].
# Creating a keyword list
list = [name: "John", age: 30]
# Accessing values
IO.puts(list[:name]) # Outputs: "John"
# Updating a keyword list
list = Keyword.put(list, :age, 31)
IO.puts(list[:age]) # Outputs: 31
# Pattern matching with keyword lists
[name: name] = list
IO.puts(name) # Outputs: "John"Structs are maps with a defined set of keys. They are defined using the defstruct macro.
defmodule User do
defstruct name: "John", age: 30
end
# Creating a struct
user = %User{name: "Alice", age: 25}
# Accessing values
IO.puts(user.name) # Outputs: "Alice"
# Updating a struct
user = %{user | age: 26}
IO.puts(user.age) # Outputs: 26Pattern matching with structs is similar to pattern matching with maps, except that you must specify the struct name.
%User{name: name} = user
IO.puts(name) # Outputs: "Alice"
# Pattern matching to ensure a specific structure
%User{} = user # This will succeed
%SomeOtherStruct{} = user # This will fail with a MatchError


