Home // Posts // Projects // About
Is immutability dragging you down? Despite what the docs claim, Elixir isn't a real functional language. We can mutate state whenever we want!
defmodule Car do defstruct [:gear, :rpm, :speed, :shift, :dealloc] # Constructor def new do state = %{ gear: 1, rpm: 1000 } {:ok, agent} = Agent.start(fn -> state end) %__MODULE__{ # Properties gear: fn -> Agent.get(agent, & &1.gear) end, rpm: fn -> Agent.get(agent, & &1.rpm) end, # Read-only property speed: fn -> Agent.get(agent, &(&1.gear * &1.rpm)) end, # Method shift: fn diff -> Agent.update(agent, fn state -> Map.update!(state, :gear, &(&1 + diff)) end) end, # Destructor dealloc: fn -> Agent.stop(agent) end } end end
And, in "use":
iex(1)> car = Car.new() %Car{ gear: #Function<3.34229322/0 in Car.new/0>, rpm: #Function<4.34229322/0 in Car.new/0>, shift: #Function<2.34229322/1 in Car.new/0>, speed: #Function<5.34229322/0 in Car.new/0>, dealloc: #Function<6.34229322/0 in Car.new/0> } iex(2)> car.gear.() 1 iex(3)> car.shift.(1) :ok iex(4)> car.gear.() 2 iex(5)> car.speed.() 2000 iex(6)> car.dealloc.() :ok iex(7)> car.gear.() ** (exit) exited in: GenServer.call(#PID<0.189.0>, {:get, #Function<9.34229322/1 in Car.new/0>}, 5000) ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started (elixir 1.14.0) lib/gen_server.ex:1038: GenServer.call/3