defmodule Structs do @moduledoc false use Koans @intro "Structs" defmodule Person do @moduledoc false defstruct [:name, :age] end koan "Structs are defined and named after a module" do person = %Person{} assert person == ___ end koan "Unless previously defined, fields begin as nil" do nobody = %Person{} assert nobody.age == ___ end koan "You can pass initial values to structs" do joe = %Person{name: "Joe", age: 23} assert joe.name == ___ end koan "Update fields with the cons '|' operator" do joe = %Person{name: "Joe", age: 23} older = %{joe | age: joe.age + 10} assert older.age == ___ end koan "Struct can be treated like maps" do silvia = %Person{age: 22, name: "Silvia"} assert Map.fetch(silvia, :age) == ___ end defmodule Plane do @moduledoc false defstruct passengers: 0, maker: :boeing end defmodule Airline do @moduledoc false defstruct plane: %Plane{}, name: "Southwest" end koan "Use the put_in macro to replace a nested value" do airline = %Airline{} assert put_in(airline.plane.maker, :airbus) == ___ end koan "Use the update_in macro to modify a nested value" do airline = %Airline{plane: %Plane{passengers: 200}} assert update_in(airline.plane.passengers, fn x -> x + 2 end) == ___ end koan "Use the put_in macro with atoms to replace a nested value in a non-struct" do airline = %{plane: %{maker: :boeing}, name: "Southwest"} assert put_in(airline[:plane][:maker], :cessna) == ___ end end