Как представить значение + единицы в YAML?
Я разрабатываю новый формат конфигурации/данных, который будет в YAML. Многие из входов представляют собой значения int/float, с соответствующими единицами (например, литр, кварт, пинта, секунда, минута,...).
Я искал и читал, но все равно не могу понять: как лучше всего связать значение и unit с элементом конфигурации в YAML
Пример: Скажем, у меня есть список из нескольких напитков и (среди прочего), я хочу ввести их объем. Я могу думать о нескольких путях, но (по крайней мере, по-моему) ни один из них не идеален:
-
Требовать, чтобы все значения тома были введены в те же единицы.
Заставляет пользователя самостоятельно выполнять преобразование блока, что является утомительным, подверженным ошибкам и трудным для проверки позже, потому что теперь количество ввода отличается от исходного количества, указанного для напитка. (Напитки поступают из нескольких разных источников, каждый из которых потенциально использует различную единицу измерения.)
-
Представьте значение с последовательностью томов и единиц. Пример:
volume: [ 0.5, Gallons ]
(Отображение будет работать также, хотя и более подробное). Последовательность может быть ОК, но я не уверен, что мне это нравится.
-
Используйте два значения "объем", один для значения, другой для единиц. Пример:
volume_value: 0.5
volume_units: Gallons
Я думаю, что это не стартер. Вербальная, очень свободная ассоциация, подверженная ошибкам.
-
Используйте вместо этого строку и проанализируйте ее в приложении. Пример:
volume: 0.5 Gallons
Проще всего войти, и очень легко написать надежный парсер. Кажется, возможно, это немного взломать, хотя...
-
Теги приложения:
volume: !gallons 0.5
Не уверен в этом, так как я новичок в YAML и еще не очень хорошо разбираюсь в тегах. Синтаксис немного более хрупкий, возможно.
Итак, вопрос в следующем: в спецификации YAML или в наилучшей практике/соглашении defacto, существует ли конкретный способ представления значений + единиц? Является ли это одним из пяти перечисленных мной или чего-то еще, Я надеюсь, что есть "правильный ответ", чтобы оставаться в пределах рекомендаций по сайту.
Ответы
Ответ 1
Вам следует серьезно изучить версию тега, так как это позволит вам сразу создать экземпляр Gallons, который может быть производным от общего класса томов, на котором вы можете выполнять нормализованные вычисления. Вы код, работающий с конфигурацией, станет более гибким.
Если это так, расширьте безопасный загрузчик, предоставляемый вашей библиотекой, особенно если у вас нет полного контроля над созданием файла конфигурации. Если вы этого не сделаете и загрузите с помощью интерпретируемого языка (perl, python, ruby), вы рискуете создать специальную конфигурацию Crafter, на которой будет запущен любой код на компьютере.
Если теги не так, как вы хотите, есть еще одна альтернатива, которую вы не предложили, это вложенные сопоставления:
volume:
Gallons: 0.5
или как однострочный:
volume: {Gallons: 0.5}
или если вы предпочитаете:
volume: {0.5: Gallons}
Вышеизложенное потребует интерпретации после загрузки, как и ваши варианты 2, 3 и 4.
Поскольку комментарий @denian об использовании строк вместо floats имеет смысл, вы могли бы, если хотите, чтобы вы делали вычисления с использованием использования фракций !decimalfraction "0.5"
. В Python (PyYAML, ruamel.yaml) вы можете настроить загрузчик YAML, поэтому вам не нужно предоставлять кавычки вокруг 0.5
, но это приведет к поплавкам all в файле, который будет загружен как строки (которые затем могут быть интерпретированы без ошибок округления с помощью создания экземпляра decimalfraction).
Ответ 2
Я не уверен в лучших практиках, но я бы использовал что-то вроде:
Coca Cola: {unit: 0.5}
Несколько более подробный вариант:
Pepsi: {value: 0.5, unit: gallons}
Другой вариант - использовать последовательности (раздел 2.4 спецификации YAML1.2)
-
name: Coca Cola
unit: gallons
value: 0.5
-
name: Pepsi
unit: gallons
value: 0.75
Проверьте спецификацию YAML, у нее действительно хорошие примеры. http://www.yaml.org/spec/1.2/spec.html
Ответ 3
Я получил это представление
volume : 0.5
volume_units : gallons
Потому что для меня более естественно использовать его вместе с предметами, которые не имеют никаких единиц. Например.
experiment_setup :
volume : 0.5
volume_units : gal
vessel: cylinder
color: red
concentration: 10
concentration_units : mol
Чем я могу называть конкретные элементы последовательно их естественными именами:
experiment_setup.volume
experiment_setup.color
а не непоследовательно, как
experiment_setup.volume.value
experiment_setup.color
или
experiment_setup.volume_value
experiment_setup.color