当前位置:  开发笔记 > 编程语言 > 正文

在宏中生成elixir结构的正确方法

如何解决《在宏中生成elixir结构的正确方法》经验,为你挑选了1个好方法。

我有以下设计模式:我有一个elixir模块,它响应增长/变化functions/0,被称为Defaults.我还有CustomConfig模块,基本上是struct,派生默认值并假设实例化如下:

%CustomConfig{ foo: "bar" }

其中,初始化属性被覆盖,其他属性被取而代之,Defaults并且那些没有具有相同名称的函数Defaults被拒绝.到现在为止还挺好.

要独立于内容(函数列表中Defaults)实现此行为,我使用宏(在其他模块中,因为在结构声明中不能使用在同一模块中定义的宏):

defmacro define_struct_with_defaults do
  quote do
    defstruct Map.to_list(
      quote do: unquote(Enum.reduce(Dict.keys(
                        Defaults.__info__(:functions)), %{}, fn(k, acc) ->
        Map.put(acc, :"#{k}", apply(Defaults, :"#{k}", []))
      end)))
  end
end

虽然这很好用,但我很确定,应该有更直接/优雅/不太麻烦的方式来实现这个功能.

所以我的问题是:如何defstructMap没有跳舞的情况下宣布这个paso doble在map-reduce周围



1> José Valim..:

你的代码中有许多你真正不需要的间接.例子:

    :"#{k}"可能只是k因为k已经是一个原子

    你不需要Dict.keys/1因为你可以在循环内的键上进行模式匹配

    您不需要地图,因为您可以直接从Enum.map(或从理解中)返回列表

    您不需要宏,因为您可以传递任何表达式 defstruct

以下是如何重写代码:

defmodule Default do
  def foo, do: 1
  def bar, do: 2
end

defmodule Config do
  data =
    # Get all functions with 0 arity and the respective default
    for {k, 0} <- Default.__info__(:functions) do
      {k, apply(Default, k, [])}
    end

  defstruct data
end

Elixir的一个好处是你可以编写自信代码.如果您利用它,您将对代码越来越有信心.

推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有