Search code examples
elixir

** (KeyError) key not found in: nil


So, I've got this struct:

defmodule Card do
  defstruct id: nil, result_numbers: [], owned_numbers: []
end

For each instance of this, I calculate the total number of owned_numbers that are in result_numbers with CardEvaluator.evaluate_card() (this bit is tested and works).

I then construct a range of values from (card.id + 1)..(card.id + value) where value is what the card evaluator returned.

I then want to recursively call my process_card_reward method with the card from each of the indexes in that range. So, if card 2 had a value of 3, I'd call process_card_reward with the 3rd, 4th, and 5th cards. I then want to sum up the total number of cards made.

I have this:

  def process_scratchcards(card_strings) do
    cards =
      card_strings
      |> Enum.map(&CardParser.parse_card/1)
      |> IO.inspect()

    total_reward = cards
      |> Enum.map(fn card -> process_card_reward(card, cards) end)
      |> Enum.sum()

    IO.puts(total_reward)
    total_reward
  end

  def process_card_reward(card, all_cards) do
    value =
      card
      |> CardEvaluator.evaluate_card()

    victory_range = (card.id + 1)..(card.id + value)
    IO.inspect(victory_range)

    num_children =
      Enum.reduce(victory_range, 0, fn n, acc ->
        acc + process_card_reward(Enum.at(all_cards,n), all_cards)
      end)

    IO.puts(num_children)

    num_children + 1
  end

However I'm getting this exception which I don't understand:

  1. test Processes test data correctly (ScratchcardsTest) test/scratchcards_test.exs:5 ** (KeyError) key :owned_numbers not found in: nil

    If you are using the dot syntax, such as map.field, make sure the left-hand side of the dot is a map code: |> Scratchcards.process_scratchcards() stacktrace: (scratchcards 0.1.0) lib/card_evaluator.ex:3: CardEvaluator.evaluate_card/1 (scratchcards 0.1.0) lib/scratchcards.ex:19: Scratchcards.process_card_reward/2 (scratchcards 0.1.0) lib/scratchcards.ex:26: anonymous fn/3 in Scratchcards.process_card_reward/2 (elixir 1.15.7) lib/enum.ex:4379: Enum.reduce/3 (scratchcards 0.1.0) lib/scratchcards.ex:25: Scratchcards.process_card_reward/2 (scratchcards 0.1.0) lib/scratchcards.ex:26: anonymous fn/3 in Scratchcards.process_card_reward/2 (elixir 1.15.7) lib/enum.ex:4379: Enum.reduce/3 (scratchcards 0.1.0) lib/scratchcards.ex:25: Scratchcards.process_card_reward/2 (scratchcards 0.1.0) lib/scratchcards.ex:26: anonymous fn/3 in Scratchcards.process_card_reward/2 (elixir 1.15.7) lib/enum.ex:4379: Enum.reduce/3 (scratchcards 0.1.0) lib/scratchcards.ex:25: Scratchcards.process_card_reward/2 (elixir 1.15.7) lib/enum.ex:1693: Enum."-map/2-lists^map/1-1-"/2 (scratchcards 0.1.0) lib/scratchcards.ex:9: Scratchcards.process_scratchcards/1 test/scratchcards_test.exs:18: (test)

How can I fix this?


Solution

  • However I'm getting this exception which I don't understand:

    test Processes test data correctly (ScratchcardsTest) test/scratchcards_test.exs:5 ** (KeyError) key :owned_numbers not found in: nil

    iex(1)> map = %{a: 1, b: 2, owned_numbers: 3}
    %{a: 1, b: 2, owned_numbers: 3}
    
    iex(2)> map.owned_numbers
    3
    
    iex(3)> map = nil
    nil
    
    iex(4)> map.owned_numbers
    ** (KeyError) key :owned_numbers not found in: nil. If
    you are using the dot syntax, such as map.field, 
    make sure the left-hand side of the dot is a map
    

    Somewhere in your test your map is nil.