Exactly what I did, and what a funny coincidence that I just had to code something super similar in the last two days:
@type double :: float()
@double_min -1.7976931348623157e308
@double_max 1.7976931348623157e308
defguard is_double(x) when is_float(x) and x >= @double_min and x <= @double_max
@spec do_stuff(double()) :: nil
def do_stuff(x) when is_double(x) do
dec = Decimal.from_float(x)
if Decimal.compare(dec, @decimal_double_min) != :lt and
Decimal.compare(dec, @decimal_double_max) != :gt do
# the float is in range, let's do stuff!
else
# out of bounds, report error.
end
# do something else and return.
nil
end
As you said, it’s definitely better than nothing. Basically everything except the typespec itself is covered. I am nervous about using >=
and <=
in the guard but my tests have shown that the comparisons are stable for these boundary values .