elixir使用另一个struct初始化struct

时间:2016-05-21 15:19:57

标签: struct elixir

如果我有以下结构怎么办?

%Registration{email: "john@gmail.com", first_name: "John", last_name: "Doe"}

我想从中创建两个不同的结构:

%Account{email: "john@gmail.com", password: nil, ...}
%Profile{first_name: "John", last_name: "Doe", age: nil, ...}

我已经看了this question,但是如果我做了

registration = %Registration{email: "john@gmail.com", first_name: "John", last_name: "Doe"}
struct(Account, registration)

我收到protocol Enumerable not implemented for %Registration{...

所以我必须使用Map.from_struct

registration = %Registration{email: "john@gmail.com", first_name: "John", last_name: "Doe"}
struct(Account, Map.from_struct(registration))

但我觉得它不是很干净。所以我只是想有更好的方法来做到这一点吗?这应该是一个非常普遍的问题,对吧?

2 个答案:

答案 0 :(得分:1)

根据文件:

  

将结构转换为地图。   它接受结构模块或结构本身并简单地删除   结构中的 struct 字段。

该功能存在是有原因的。我真的没有看到你做这件事的方式。如果这是一个常见的问题我以前还没有见过。如果您想要更具表现力或更清晰的代码,您可以尝试:

registration = %Registration{email: "john@gmail.com", first_name: "John", last_name: "Doe"} |> Map.from_struct
struct(Account, registration)

或其他等效代码,请查看文档here

答案 1 :(得分:1)

你可以轻松地做到这一点,但有点笨拙 - 只需将协议功能委托给$('#btnSearch').click(function () { console.clear(); $.ajax({ url: "/history/list", data: { startDate: $('#startDate').val(), endDate: $('#endDate').val(), }, type: "GET", dataType: "html", success: function (data) { var result = $('<div />').append(data).find('#historyList').html(); $('#historyList').append(result); console.log(result); // the result is displayed correctly in the console... }, error: function (xhr, status) { alert("Sorry, there was a problem!"); }, complete: function (xhr, status) { //$('#showresults').slideDown('slow') } }); });

Enumerable.Map

或以更合适的方式,如


  defmodule Contact do
    defstruct [:name, group: "", version: "", status: :latent]

    defimpl Enumerable, for: Contact do
      defdelegate([count(e), member?(e, m), reduce(e, a, f)], 
                  to: Enumerable.Map)
    end
  end
可以使用宏生成

defmodule Contact do defstruct [:name, group: "", version: "", status: :latent] defimpl Enumerable do alias Enumerable, as: E def count(c), do: Map.from_struct(c) |> E.count() def member?(c, m), do: Map.from_struct(c) |> E.member?(m) def reduce(c, a, f), do: Map.from_struct(c) |> E.reduce(a, f) end end 实现,以返回编译时已知的struct members count。 Enumerable.count也可以使用宏生成或手动编写或再次委派给Enumerable.member?以消除Enumerable.Map.member?的运行时惩罚。

上面的所有代码都是通用的,因此它可以放在Map.from_struct - 像

这样的模块中
use

并将其嵌入


defmodule StructEnumerable do
  defmacro __using__(opts \\ []) do
    quote do
      defimpl Enumerable do
        alias Enumerable, as: E
        def count(c), do: Map.from_struct(c) |> E.count()
        def member?(c, m), do: Map.from_struct(c) |> E.member?(m)
        def reduce(c, a, f), do: Map.from_struct(c) |> E.reduce(a, f)
      end

      # you can also add following code
      # to provide Fetch behaviour implementation
      # for your structs
      defdelegate([
        fetch(t, k),
        get_and_update(t, k, l)
      ], to: Map)
    end
  end
end