Elixir:模式匹配函数参数到结构

Elixir: pattern match function arguments to struct

使用 {: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.

怎么了?是否有可能将函数参数与结构匹配?

你真的想写这个吗:

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

问题原因

中,函数调用中的括号不是强制性的(尽管是可取的。)也就是说,代码 def foo(bar baz) do ... 被解析并被视为 def foo(bar(baz)) do ... 因为解析器建议省略调用函数 bar 时的括号。你应该从编译器那里得到一个 warning,准确地说。应该阅读并删除警告。

快速修复

正如@peaceful-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

结构键

但是 中的结构只能将 atom 作为键。也就是说,如果您的初始代码接受了 %{"code" => _},则无法在不修改调用代码的情况下将其变成接受结构。

输入内容

类型不是 中的 first-class 公民。我个人觉得很合适。您应该从了解语言、OTP 原则、语言范式开始 ,然后才 决定您是否想要 and/or 需要类型。