Rudziankoŭ
Rudziankoŭ

Reputation: 11251

Elixir: pattern match function arguments to struct

Using {:typed_struct, "~> 0.2.1"} library I have following struct:

  defmodule RequestParams do
    use TypedStruct
    typedstruct do
      field :code, String.t()
      field :name, String.t()
    end
  end

I am trying to pattern match function parameters to struct:

def do_handle(params %RequestParams{}, _context) do
# instead of
# def do_handle(%{ "code" => code, "name" => name}, _context) do

But I get exception:

cannot find or invoke local params/2 inside match. Only macros can be
invoked in a match and they must be defined before their invocation.

What is wrong? And is it possible at all to match function parameters to struct?

Upvotes: 0

Views: 3839

Answers (2)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Cause of the issue

In , parentheses in function calls are not mandatory (although desirable.) That said, the code def foo(bar baz) do ... is being parsed and treated as def foo(bar(baz)) do ... because the parser suggests omitted parentheses in call to the function bar. You should have got a warning from the compiler, saying exactly that. Warnings are supposed to be read and eliminated.

Quick fix

As it is pointed out by @peaceful-james, pattern matching inside parentheses would do.

def do_handle(%RequestParams{} = params, _context) do

“Instead of”

You wrote

def do_handle(params %RequestParams{}, _context) do
# instead of
# def do_handle(%{ "code" => code, "name" => name}, _context) do

Even if it was syntactically correct, the code above is not equivalent to the code below. The code below would accept any map, having two keys "code" and "name", while the code above allows instances of RequestParams only. One might also make the code below more strict with:

def do_handle(%RequestParams{code: code, name: name}, _) do

Struct keys

But structs in cannot have anything but atom as a key. That said, if your initial code accepted %{"code" => _} there is no way to turn it into accepting a struct without modifying the calling code.

Typed stuff

Types are not the first-class citizens in . I personally find it appropriate. You should start with understanding the language, OTP principles, the paradigm of the language and only after that decide whether you want and/or need types at all.

Upvotes: 6

Peaceful James
Peaceful James

Reputation: 2235

Do you actually mean to write this:

def do_handle(%RequestParams{}=params, _context) do

Upvotes: 3

Related Questions