有没有办法让 Elixir 记录没有默认值?
Is there a way to have Elixir Records without default values?
背景
我正在尝试寻找一种在 Elixir 中创建新类型的廉价且简单的方法,Records 似乎正是我所需要的。
问题
但是,Elixir 记录需要一个来定义默认值。不仅如此,它还允许创建空记录(然后将用所述默认值填充)。
对于我的特定用例,这是一个问题。我不仅没有任何可以用作默认值的东西,我也不想让我的代码的用户创建空记录。
现在,我知道这可能是一个有意为之的选择,很可能是因为它可以很好地与 Erlang 记录交互,但它会导致我这边的可用性问题:它允许创建无效数据。
问题
我知道仅使用 Records 可能没有解决这个难题的方法,所以我想知道是否有图书馆的替代品,甚至黑客来完成这个。
我个人一无所获,现在我觉得我唯一的解决办法就是编写自己的宏。
- 有没有办法让 Records 不接受默认值?
- 如果不是,有哪些社区图书馆可以帮助完成创建新类型的角色?
回答
- 有没有办法让 Records 不接受默认值?
没有。这对于 Records 是不可能的。记录从来就不是为这个用例设计的,将这种抽象强加到它们中只会使事情复杂化。虽然可以使用包装器 new
方法,但它仍然是很多样板文件,并且所有类型验证都将由用户完成。
- 在撰写本文时,有 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
背景
我正在尝试寻找一种在 Elixir 中创建新类型的廉价且简单的方法,Records 似乎正是我所需要的。
问题
但是,Elixir 记录需要一个来定义默认值。不仅如此,它还允许创建空记录(然后将用所述默认值填充)。
对于我的特定用例,这是一个问题。我不仅没有任何可以用作默认值的东西,我也不想让我的代码的用户创建空记录。
现在,我知道这可能是一个有意为之的选择,很可能是因为它可以很好地与 Erlang 记录交互,但它会导致我这边的可用性问题:它允许创建无效数据。
问题
我知道仅使用 Records 可能没有解决这个难题的方法,所以我想知道是否有图书馆的替代品,甚至黑客来完成这个。
我个人一无所获,现在我觉得我唯一的解决办法就是编写自己的宏。
- 有没有办法让 Records 不接受默认值?
- 如果不是,有哪些社区图书馆可以帮助完成创建新类型的角色?
回答
- 有没有办法让 Records 不接受默认值?
没有。这对于 Records 是不可能的。记录从来就不是为这个用例设计的,将这种抽象强加到它们中只会使事情复杂化。虽然可以使用包装器 new
方法,但它仍然是很多样板文件,并且所有类型验证都将由用户完成。
- 在撰写本文时,有 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