Pattern Matching Map

hey,
So I have this function
def update(
conn,
%{
“expense_id” => id,
“name” => _name,
ocr => _ocr

    } = payload
  ) do ...

my ocr field is a map that I’m going to update :
when I compiled my code I had : cannot use variable ocr as map key inside a pattern. Map keys in patterns can only be literals (such as atoms, strings, tuples, etc.) or an existing variable matched with the pin operator (such as ^some_var) as error
Do you have any suggestions? did any one get by this problem?

Is the key for ocr content dynamic or static, e.g. "ocr" or :ocr ?

If it is dynamic, you can use is_map_key/2 guard, but I really doubt it because it seems you’re using Phoenix and it’s unlikely to have dynamic field names in general.

1 Like

ocr has dynamics keys for the moment (I’ll define a struct later for it so it will be static ) And yes I’m using Phoenix.
Thank you for your answer

What would be the key that ocr represents?

name , language

There’s really no way of knowing what that pattern match means at compile time, the options I see is to either use is_map_key as @qhwa mentions, like:

def update(conn, %{"expense_id" => id, "name" => _name} = params
) when is_map_key(params, "language") or is_map_key(params, "another_key") do ....

But you’ll probably have to handle then, down the line, which param was actually passed, so you don’t gain that much other than validating that at least one of those keys is present.

Or having multiple update function definitions, one for each expected key, pattern matching the exact key on each one (then in the body of update you’ll know exactly which one you’re dealing with), or to have a function that validates the map, called inside the update controller action and take it from there.

Without knowing what is the whole intended flow not sure what would be the best option.

2 Likes