Journal Entry, September 27th to October 4th 2019

October 4, 2019 · 3 min read

Elixir Koans

  1. Wed Oct 2

    • Used asdf over docker image
    • Docker had issues installing the filesystem dependency?
    • Looks like docker works after asdf. My guess is it needed the deps directory as if docker isn't sharing the directory normally.
    • Structs

      • Is %Person{} right for the first answer? I looked at the code, not the text to answer it.
    • Sigils
    • Pattern Matching

      • Very difficult to reason about this example
      assert_raise MatchError, fn ->
          [a, b] = [1, 2, 3]
      end
      koan "The pattern can make assertions about what it expects" do
          assert match?([1, _second, _third], [1, 2, 3])
      end
      • It helps to remember that it's looking for the pattern that gets pulled out, not a left = right scenario
      • I clearly don't understand this part and it's one of the more powerful aspects of the language. I don't even know where to begin to get a deeper understanding of how to use it.
    • Functions

      • Understand the default in this case was 5
      koan "Functions can have default argument values" do
          assert repeat_again("Hello ") == "Hello Hello Hello Hello Hello "
          assert repeat_again("Hello ", 2) == "Hello Hello "
      end
      • Understand the function was building output, look for things like [] or {}
      koan "You can build anonymous functions out of any elixir expression by prefixing it with &" do
          three_times = &[&1, &1, &1]
          assert three_times.("foo") == ["foo", "foo", "foo"]
      end
      • Understand the flow of FP, take the first result 10 then pipe it to the second result, square 100. Then divide by 1
      koan "You can pass functions around as arguments. Place an '&' before the name and state the arity" do
          assert times_five_and_then(2, &square/1) == 100
      end
    • Enums

      • Seems that anything with ? becomes a boolean check or it's just how it's used in all of these examples based on how they define functions
      koan "Elements can have a lot in common" do
          assert Enum.all?([1, 2, 3], &less_than_five?/1) == true
          assert Enum.all?([4, 6, 8], &less_than_five?/1) == false
      end
      • Take the first 3, not take the literal instance of 3
      koan "You three there, follow me!" do
          assert Enum.take([1, 2, 3, 4, 5], 3) == [1, 2, 3]
      end
      • I have a feeling this syntax is important
      koan "Zip-up in pairs!" do
          letters = [:a, :b, :c]
          numbers = [1, 2, 3]
          assert Enum.zip(letters, numbers) == [a: 1, b: 2, c: 3]
      end
      • Unsure why 4 doesn't work here. Does it return the first element?
      koan "When you want to find that one pesky element" do
          assert Enum.find([1, 2, 3, 4], &even?/1) == 2
      end
  2. Thu Oct 3

    • Processes

      koan "You can ask a process to introduce itself" do
          information = Process.info(self())
      
          assert information[:status] == :running
      end
      • It's hard to really understand where this would be useful except to spawn processes or to cleanup/log on exit
    • Tasks
    • Agents

      • It's also hard to understand the use cases for pretty much all the above, processes, tasks, and agents. There seems to be a bit of overlap between them.
    • GenServers

      • This is perhaps one of the more extensive and fun as the response is in the declaration (like most of these) but it's more about hunting and finding the response you expect.
      • One of the best examples of pattern matching, or anything shows as less emphasis in VSCode's syntax highlighting
      koan "Let's use the remaining functions in the external API" do
          Laptop.start_link("EL!73")
          {_, response} = Laptop.unlock("EL!73")
          assert response == "Laptop unlocked!"
      
          Laptop.change_password("EL!73", "Elixir")
          {_, response} = Laptop.unlock("EL!73")
          assert response == "Incorrect password!"
      
          {_, response} = Laptop.owner_name()
          assert response == "Jack Sparrow"
      end
    • Protocols

      • Seem like implementation details and helpful for defining contracts and concrete definitions. It's a little unclear what the preference for using this is.
    • Comprehensions

      • A little harder to understand this is multiple lists not coercing to one long string. I tried "Hello World Apple Pie" at first.
      koan "A generator specifies how to extract values from a collection" do
          collection = [["Hello","World"], ["Apple", "Pie"]]
          assert (for [a, b] <- collection, do: "#{a} #{b}") == ["Hello World", "Apple Pie"]
      end
      • Turns out this one is unlike the one before it where my initial instincts were closer to correct.
      koan "You can use multiple generators at once" do
          assert (for x <- ["little", "big"], y <- ["dogs", "cats"], do: "#{x} #{y}") == ["little dogs", "little cats", "big dogs", "big cats"]
      end