Keyword List

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

7 Comments

  1. Jaison Vieira on November 7, 2021 at 7:04 am

    I found an issue with the test `refactoring rounded/2`. The test case is setting the key :decimals to nil. Instead it should set the opts parameter to nil.

    This:
    assert 1.2346 == Keywords.rounded(1.2345678, decimals: nil)

    Should be:
    assert 1.2346 == Keywords.rounded(1.2345678, nil)

    • Jaison Vieira on November 7, 2021 at 7:14 am

      Or did I miss anything here? Because setting decimals key to nil makes no difference here to using the default value.

      This works on all cases and I don’t need to add the logical OR:

      decimals = Keyword.get(opts, :decimal, 4)
      
      • Mark Ericksen on November 7, 2021 at 12:57 pm

        setting decimals key to nil makes no difference here to using the default value.

        That’s right. The problem description here is “When the value used for the number of decimals was loaded from the database, they found there are situations when it is nil.” Part of the challenge in creating practice exercises is making up a somewhat realistic situation. This situation (I admit it’s contrived!), is assuming that the number of decimals that we’ll round to is a value returned from the database. This could be like an account configuration setting.

        The point is that the number decimals value may be nil. So it would be nice if the function could use the default setting when it gets a nil. If the value used for the decimals is nil, then this code does NOT give us what we want. It’s because the nil was explicitly provided, so it will be used instead of the default value of 4 that we want.

        opts = [decimals: nil]
        decimals = Keyword.get(opts, :decimals, 4)
        decimals
        #=> nil
        

        We want it to use the default value of 4 when it’s nil. So this logical OR does that.

        opts = [decimals: nil]
        decimals = Keyword.get(opts, :decimals) || 4
        decimals
        #=> 4
        

        This is attempting to show a common pattern used in Elixir for dealing with keyword lists as options and how we may need to do something special with a nil value and why.

        So to answer your first question, this is intentionally passing the decimals: nil into the function. It’s saying, “lets not worry about changing the WAY we call the function based on the value, but have 1 way to call it and make it handle the possible different input values.” Going one step further, it’s trying to show a simple and elegant way to do that.

        I hope that helps!

        • Jaison Vieira on November 8, 2021 at 9:19 pm

          Gotcha!!! It makes total sense now. I was overlooking based on the test cases instead of looking as a real world scenario.
          Thank you so much!

  2. Maksym Kosenko on April 3, 2022 at 7:52 am

    Great explained the topic!!!! 👍 👍 👍

  3. Maksym Kosenko on April 3, 2022 at 9:03 am

    1. About exercise 3 >>

    %Item{} = item doesn’t work in my env, it gives an error like:

    ** (CompileError) lib/keywords.ex:19: Item.__struct__/0 is undefined, cannot expand struct Item. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
        (stdlib 3.17.1) lists.erl:1358: :lists.mapfoldl/3
    

    2. :erlang.float_to_binary … doesn’t work either ¯\_ (ツ)_/¯

    3. The working solution which passes all the test in my environment is the following:

    def unit_price(item, opts \\ []) do
        unit_price = item.price / item.quantity
        case Keyword.get(opts, :mode) do
          :money -> Float.to_string(unit_price, decimals: 2)
          _ -> unit_price
        end
      end
    

    About my env:

    asdf current
    returns 
    elixir          1.12.2-otp-24
    
    • Mark Ericksen on April 4, 2022 at 6:30 am

      The struct error is likely from a missing or incorrect alias. It’s saying, “I don’t know what the ‘Item’ struct is.” Check for the alias.

      If you open IEx in a terminal and try the following you’ll see you should be :erlang.float_to_binary.

      :erlang.float_to_binary(1.2121, decimals: 1)     
      "1.2"
      
      Float.to_string(1.2121, decimals: 1)               
      warning: Float.to_string/2 is deprecated. Use :erlang.float_to_binary/2 instead
        iex:1
      
      $ asdf current
      elixir          1.13.0
      erlang          24.1
      

Leave a Comment

You must be logged in to post a comment.