elixir - 如何在 Ecto 中存储 Elixir 函数?

标签 elixir ecto

我想要一个包含“操作”字段的数据库表。我想在现场存储一个 Elixir 函数。这可能吗?

该函数始终只接受一个参数。

最佳答案

这是我过去使用过的一种 Ecto 类型,它与上面评论中链接的 @AbM 非常相似:

defmodule ErlangETF do
  def type, do: :binary

  def cast(binary = << 131, _ :: binary >>) do
    try do
      {:ok, :erlang.binary_to_term(binary)}
    catch
      _ ->
        {:ok, binary}
    end
  end
  def cast(any), do: {:ok, any}

  def load(any), do: cast(any)

  def dump(any), do: {:ok, :erlang.term_to_binary(any)}
end

模型的架构定义可能如下所示:

defmodule Example do
  use Ecto.Model

  schema "examples" do
    field :function, ErlangETF
  end
end

如果您想进一步限制允许的术语类型(例如,仅允许元数为 1 的函数),类似这样的操作可能会起作用:

defmodule ErlangFunctionArity1ETF do
  def type, do: :binary

  def cast(binary = << 131, _ :: binary >>) do
    try do
      case :erlang.binary_to_term(binary) do
        function when is_function(function, 1) ->
          {:ok, function}
        _ ->
          {:ok, binary}
      end
    catch
      _ ->
        {:ok, binary}
    end
  end
  def cast(any), do: {:ok, any}

  def load(any), do: cast(any)

  def dump(function) when is_function(function, 1),
    do: {:ok, :erlang.term_to_binary(function)}
  def dump(_),
    do: {:ok, nil}
end

您还可以在外部术语格式中存储两种格式的函数:

  1. EXPORT_EXT
  2. NEW_FUN_EXT

以下是 EXPORT_EXT 和生成的字节大小的示例:

iex> (&Enum.sum/1) |> ErlangFunctionArity1ETF.dump |> elem(1) |> byte_size
24

以下是 NEW_FUN_EXT 和生成的字节大小的示例:

iex> (fn c -> Enum.sum(c) end) |> ErlangFunctionArity1ETF.dump |> elem(1) |> byte_size
228

我提到了字节大小差异,以防存储大小成为问题。

EXPORT_EXT 本质上只存储 2 个原子和 1 个整数(:Enum:sum1)这就是序列化函数的大小如此之小的原因。匿名函数被序列化为 NEW_FUN_EXT,它存储所有函数代码及其创建信息。

关于elixir - 如何在 Ecto 中存储 Elixir 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34079938/

相关文章:

docker - 使用Docker-Compose UP进行Elixir测试

elixir - 如何在 Elixir Phoenix 框架中指定 URL 中的参数格式?

json - 为自引用 Ecto 模型构建 JSON 映射

elixir - Ecto 查询中正则表达式的正确语法是什么?

elixir - 无法在使用 Ecto 迁移时为字符串数组列( Elixir 列表)创建默认值

elixir - 我如何理解 ecto 中的迁移是上升还是下降?

elixir - 我可以将管道和更新语法与结构一起使用吗?

shell - 使用 Mix 时 Elixir .exs 脚本 "module is not loaded and could not be found"

Elixir /Phoenix : Missing beam file elf_format <<"/usr/lib/erlang/lib/hipe-3.11.2/ebin/elf_format.beam"

elixir - 在预加载中添加 Group By 子句