I was doing some warmup exercises and ran into some unexpected behaviour.
The original code and its inlined version
def bday_pdox(n : Int32) : Float64
diff = (365 - n + 1..365).product
all = 365**n
1 - diff/all
end
def bday_pdox_inlined(n : Int32) : Float64
1 - (365 - n + 1..365).product/365**n
end
caused an OverflowError once n got too large. Annoying, but not unexpected. So I switched to floating point numbers:
def bday_pdox_inlined(n : Int32) : Float64
1 - (365 - n + 1..365).product(&.to_f64)/365.0**n
end
Now crystal tool format complained about a syntax error at the /:
syntax error in ‘./birthday_paradox.cr:35:45’: unexpected token: “DELIMITER_START”
I had to add another – unexpected – pair of parentheses to get the code to compile:
def bday_pdox_inlined(n : Int32) : Float64
1 - ((365 - n + 1..365).product(&.to_f64))/365.0**n
end
The same behaviour happens when I use a block {|n| n.to_f64} instead of the short version but in that case, the parentheses are not unexpected as blocks as final arguments inside complex expressions don’t mesh well.
I assume that the short version gets macro expanded to the full block which then causes the problem. Explainable, but unexpected.
Is that something that can be fixed in crystal or do I need to train my crystal eye to watch out for &.?
Regards,
s.