Я пытаюсь найти дешевый и простой способ создания новых типов в Эликсире, и Рекорды кажется именно тем, что мне нужно.
Однако записи Elixir требуют, чтобы они определяли значения по умолчанию. Мало того, он также позволяет создавать пустые записи (которые затем будут заполнены указанными значениями по умолчанию).
Для моего конкретного случая использования это проблема. Мало того, что у меня нет ничего, что можно было бы использовать в качестве значения по умолчанию, я также не хочу позволять пользователям моего кода создавать пустые записи.
Теперь я понимаю, что это, вероятно, хорошо продуманный выбор, скорее всего, чтобы он мог хорошо взаимодействовать с записями Erlang, но это вызывает проблему с удобством использования с моей стороны: это позволяет создавать недействительные данные.
Я понимаю, что, вероятно, нет решения этой головоломки с использованием только записей, поэтому мне было интересно, есть ли альтернативы в диких библиотеках или даже хаки для этого.
Я лично ничего не нашел, сейчас у меня такое чувство, что мое единственное решение - написать свой собственный макрос.
Да, у меня есть. Вы можете сделать это, но здесь задействовано много шаблонов, поэтому моя идея для макроса.
Запись предназначена для использования, когда вам нужно работать с короткими внутренними данными. Если вам нужна проверка, чтобы избежать неверных данных и значений по умолчанию, я думаю, что запись не является рекомендуемой структурой данных. Это неправильный инструмент для работы.
Мы согласны с этим!
Нет. Это невозможно с Records. Записи никогда не предназначались для этого варианта использования, и внедрение в них этой абстракции только усложнило бы ситуацию. Хотя можно было бы использовать метод-оболочку new
, это все равно будет много шаблонного, и вся проверка типа будет на пользователе.
В этом посте я предлагаю API, а затем улучшаю его с помощью сообщества. Для тех из вас, кому любопытно, его можно использовать следующим образом:
тип.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
Просто удостоверяюсь, но вы изучили структуры и атрибут
@enforce_keys
?