首页 > 解决方案 > Elixir 中与 Ruby 中的实例变量有什么相似的用法?

问题描述

我目前正在努力满足这个要求。例如,我有一个函数列表。

def function_a(a, b, c, d) do
  ...
  function_b(a, b)
  ...
end

defp function_b(a, b) do
  ...
  function_c(a, b)
  ...
end

defp function_c(a, b) do
  ...
  function_d(a, b)
  ...
end

defp function_d(a, b) do
  IO.inspect a
  IO.inspect b
end

现在我想IO.inspect dfunction_d. 我能想到的唯一方法是将 d 作为每个函数的参数传递。这意味着我需要修改function_b, function_c, function_d(在现实世界中,它更多)。

在 OOP 世界中,我们可以将 存储d为实例变量,该类中的任何函数都可以直接使用它。

我问这个问题的原因是我想避免增加参数的数量。

Elixir或Phoenix有什么好方法吗?

标签: elixir

解决方案


Sabiwara在评论中的建议很好。如果您遵循将结构作为第一个参数传入函数并从每个参数返回结构的约定,则可以非常轻松地编写管道链。

defmodule Example do
  defstruct ~w(a b c d)a

  def function_a(%Example{} = example) do
    IO.inspect(example.a, label: "a")
    example
  end

  def function_b(%Example{} = example) do
    IO.inspect(example.b, label: "b")
    example
  end

  def function_c(%Example{} = example) do
    IO.inspect(example.c, label: "c")
    example
  end

  def function_d(%Example{} = example) do
    IO.inspect(example.d, label: "d")
    example
  end

  def call_all() do
    %Example{a: "I'm a", b: "this is b", c: "C too", d: "Finally d"}
    |> function_a()
    |> function_b()
    |> function_c()
    |> function_d()
  end
end

在 iex 中运行:

iex(1)> Example.call_all
a: "I'm a"
b: "this is b"
c: "C too"
d: "Finally d"
%Example{a: "I'm a", b: "this is b", c: "C too", d: "Finally d"}

我不想使用这种方式,因为它破坏了代码的某些含义。

Elixir 模块没有状态——只有函数和参数。无法从另一个函数访问一个函数中的参数。如果您想避免使用新参数,您要么需要使用两个函数都知道的数据结构,要么将状态存储在某处(在流程、ETS、流程字典中......)。


推荐阅读