有没有办法让 Elixir 记录没有默认值?

Is there a way to have Elixir Records without default values?

背景

我正在尝试寻找一种在 Elixir 中创建新类型的廉价且简单的方法,Records 似乎正是我所需要的。

问题

但是,Elixir 记录需要一个来定义默认值。不仅如此,它还允许创建空记录(然后将用所述默认值填充)。

对于我的特定用例,这是一个问题。我不仅没有任何可以用作默认值的东西,我也不想让我的代码的用户创建空记录。

现在,我知道这可能是一个有意为之的选择,很可能是因为它可以很好地与 Erlang 记录交互,但它会导致我这边的可用性问题:它允许创建无效数据。

问题

我知道仅使用 Records 可能没有解决这个难题的方法,所以我想知道是否有图书馆的替代品,甚至黑客来完成这个。

我个人一无所获,现在我觉得我唯一的解决办法就是编写自己的宏。

回答

  1. 有没有办法让 Records 不接受默认值?

没有。这对于 Records 是不可能的。记录从来就不是为这个用例设计的,将这种抽象强加到它们中只会使事情复杂化。虽然可以使用包装器 new 方法,但它仍然是很多样板文件,并且所有类型验证都将由用户完成。

  1. 在撰写本文时,有 none。但是,在另一个 post 中,我创建了一个实现此目的的宏:https://elixirforum.com/t/how-to-define-macro-for-a-new-type/46852/10?u=fl4m3ph03n1x

在那个 post 中,我提出了一个 API,然后我在社区的帮助下对其进行了完善。好奇的小伙伴可以这样用:

type.ex

defmodule Type do
  import NewType

  deftype(Name, String.t())
end

test.ex

defmodule Test do
  alias Type.Name

  @spec print(Name.t()) :: binary
  def print(name), do: Name.extract(name)

  def run_1 do
    # dialyzer complains !
    Name.new(1)
  end

  def run_2 do
    # dialyzer complains !
    print("john")
  end

  @spec run_3 :: binary
  def run_3 do
    print(Name.new("dow"))
  end
end