Pattern Matching a Function Body: Struct

You cannot view this unit as you're not logged in yet. Go to Account to login.

11 Comments

  1. McKinnin Lloyd on January 27, 2020 at 10:04 pm

    I have a question. Why in the function get_name it will throw an error if you do %User{name: name} and not %{name: name}, but in the create_greeting function it is opposite. In that function it wants you to do %User{name: name}?

    • brainlid on January 28, 2020 at 6:20 am

      That’s a good question! In the get_name example, we want the pattern to be less specific. By not specifying the struct type, we match on any map data type (including structs) but only if they have a key called :name. For get_name, it would also be valid to write this:

      def get_name(%Customer{name: name}), do: {:ok, name}
      def get_name(%User{name: name}), do: {:ok, name}
      def get_name(_other), do: {:error, "Doesn't have a name"}

      This is more specific. We give an explicit pattern match on a customer and user struct. However, the results of the functions are identical. It doesn’t actually matter that it’s a Customer or a User struct type. It is better to match more generally to only the data that we actually care about for getting the :name from the data.

      Then in the create_greeting function we want to be more specific with our match because we want a different result based on the data type.

      Another way to describe the behavior in get_name is like this: “if the data has a key called :name then return the value”. It doesn’t care about what kind of struct. Then create_greeting is saying “if it is a customer then greet this way. If it is a user then greet this other way.” The best way to tell them apart is by their struct types.

      Did I answer your question?

  2. romenigld on December 14, 2020 at 7:42 am

    I loved this example.
    It’s like when you will refactor the code.
    You match on any map data type (including structs) and has less lines of code to write and understand.
    Thank’s!

  3. Mark Johnson on February 22, 2021 at 1:22 am

    Another really great exercise. Thank you for taking the effort to do this for all of us trying to learn

  4. Alister Sibbald on April 14, 2021 at 6:50 am

    Great lessons – Thanks! I’m really internalising the Elixir way thanks to these!

    Could I ask you how you got the great colorization of IEX as seen in the first code example on this page?

    • Mark Ericksen on April 14, 2021 at 7:15 am

      For the colors, on this page it’s just text using a web syntax highlighter for the Elixir language. So it didn’t come out of my IEx terminal looking like that. Sorry!

  5. Pavel Delgado on August 29, 2021 at 1:26 pm

    Hi ! What is the main difference between using %{key: value} and %{key => value} ? . Thanks for the great lessons.

    • Mark Ericksen on August 30, 2021 at 5:33 am

      When the key is an atom, it can use the %{key: value} form. When the key is a string or other data structure, it uses the “arrow” form. It is also valid to write %{:key => 1}. When you write that in IEx, you will see it returned as %{key: 1}. So it’s really “syntactic sugar” that makes maps more readable when the key is an atom. It was initially covered here: https://thinkingelixir.com/course/pattern-matching/module-2/map/

  6. Takudzwa Gwindingwi on November 2, 2021 at 11:03 am

    Loving this course. Also enjoying reading the comments. Could you kindly explain how we were using the Customer and User structs in the structs.ex when they are defined in their respective files.

    • Mark Ericksen on November 4, 2021 at 6:55 am

      I think you are asking how the structs can be referenced without something like an “include” or “require”? That’s at least the question I’ll try to answer. In Elixir, all modules and types are available globally. There is no need to “require” or “import” or anything like that. What keeps them separate and organized is their namespace. So you could reference a struct using it’s full name like this: %PatternMatching.Customer{} at anytime anywhere in your code. However, that can be awkward and verbose. If you have a file that repeatedly deals with that struct, it’s common to “alias” it at the top of the file. This only creates a shortcut to the name you want to reference inside the module you are writing.

      In the code and test files, it looks like this: alias PatternMatching.{Customer, User}. Aliasing multiple things at a time like this (using the {}) is discouraged. It’s considered a bad practice because it’s confusing and doing a Find/Replace doesn’t work well.

      I had forgotten that the examples used this approach and I should update them to be a better example. It should instead be like this:

      alias PatternMatching.Customer
      alias PatternMatching.User
      

      I hope that answered the question you were asking!

  7. Maksym Kosenko on December 5, 2021 at 5:59 am

    Thanks Mark! These’re great explanations of Struct. I like the way of studying through examples ⛰️

Leave a Comment

You must be logged in to post a comment.