#keyword doesn't return nil when #env var is missing
fuadsaud opened this issue · comments
Hi!
I don't really understand if this is a bug or a misuse of tagged literals on my part. I want to specify a :logger/min-level
key which could contain either a keyword or a complex data structure. I want to source the value either from an environment variable LOGGER_MIN_LEVEL
, in which case I would like the string to be coerced into a keyword, or from a #profile
dispatch. Here's what I tried:
:logger/min-level #or [#keyword #env LOGGER_MIN_LEVEL
#profile {:default :info
:development
[[#{"some-ns.*"} :trace]
[#{"*"} :info]]
:test
[[#{"some-ns.*"} :trace]
[#{"*"} :info]]}]
In the scenario where the env variable is not set, this returns an empty keyword :
. Removing the #keyword
tag from the above example makes it work (without the proper coercion, of course). If I understand correctly, #keyword
is trying to coerce the vector, which generates the empty keyword. Is this the correct way to approach the problem?
I don't think #or
is relevant here particularly. #keyword
always converts anything it gets to a keyword:
Lines 73 to 77 in 814b000
some->
Is this perhaps a misunderstanding on my end about application precedence or tagged literals? My intuition led me to interpret the above as:
(#or (#keyword (#env LOGGER_MIN_LEVEL))
(#profile ...))
But it seems that #keyword applies to both branches of the #or.
(#or (#keyword (#env LOGGER_MIN_LEVEL))
(#profile ...))
is correct!
But the problem is that (#keyword (#env LOGGER_MIN_LEVEL))
becomes (keyword (str nil))
which is (keyword "")
which produces :
and that causes your problem!
You could solve this by introducing a new method which behaves a little more like you expect:
(defmethod aero/reader 'ns/kw
[opts tag value]
(if (keyword? value)
value
(some-> value keyword)))
Usage of:
#or [#ns/kw #env LOGGER_MIN_LEVEL #profile {...}]`
should work then.
@SevereOverfl0w ah, that makes perfect of sense, thanks for taking the time to elaborate.