Эликсир: аргументы функции сопоставления с образцом для структуры - PullRequest
0 голосов
/ 04 августа 2020

Использование {: typed_struct, "~> 0.2.1"} библиотека У меня есть следующая структура:

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

Я пытаюсь сопоставить параметры функции с шаблоном для структуры:

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

Но я получаю исключение:

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.

Что не так? И возможно ли вообще сопоставить параметры функции со структурой?

Ответы [ 2 ]

2 голосов
/ 05 августа 2020

Причина проблемы

В скобки в вызовах функций не являются обязательными (хотя и желательны). Тем не менее, код def foo(bar baz) do ... анализируется и обрабатывается как def foo(bar(baz)) do ... потому что парсер предлагает опустить круглые скобки при вызове функции bar. Вы должны получить предупреждение от компилятора, говорящее именно об этом. Предупреждения должны быть прочитаны и устранены.

Быстрое исправление

Как указано в @ peace-james, подойдет сопоставление с образцом в круглых скобках.

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

«Вместо»

Вы написали

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

Даже если он был синтаксически правильным, приведенный выше код не эквивалентен приведенному ниже коду. Приведенный ниже код принимает любую карту с двумя ключами "code" и "name", тогда как приведенный выше код допускает только экземпляры RequestParams. Можно также сделать приведенный ниже код более строгим, используя:

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

Struct keys

Но структуры в не могут иметь ничего, кроме atom в качестве ключа. Тем не менее, если ваш первоначальный код принят %{"code" => _}, невозможно превратить его в принятие структуры без изменения вызывающего кода.

Типизированный материал

Типы не являются первоклассными гражданами в . Я лично считаю это уместным. Вы должны начать с понимания языка, принципов OTP, парадигмы языка и только после этого решить, нужны ли вам типы и / или нужны ли они вообще.

2 голосов
/ 05 августа 2020

Вы действительно хотите написать это:

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