logoalt Hacker News

Alupis10/11/20241 replyview on HN

The divide-by-zero thing is explained here[1]. The relevant bits:

> Gleam does not implicitly throw exceptions, so throwing an exception is not an option. The BEAM VM does not have a Infinity value, so that is not an option. Therefore Gleam returns 0 when dividing by zero.

> The standard library provides functions which return a Result type for division by zero which you can use if that is more suitable for your program.

You can also use Guards[2] to prevent handle a divide-by-zero situation before you attempt it.

[1] https://gleam.run/frequently-asked-questions/#why-does-divis...

[2] https://tour.gleam.run/everything/#flow-control-guards


Replies

josevalim10/12/2024

I know you are quoting the docs, but Gleam absolutely throws implicit exceptions, for exactly the same reason why it returns 0 when dividing: the Erlang/VM does not support Infinity/NaN, which means floating point operations can also overflow/underflow. For example, any division with a subnormal will raise:

    1.0 /. 5.0e-324
Or addition between really large floats:

    1.0e308 +. 1.0e308
In fact, even the `float.divide` function, which is meant to be safe, will raise:

    float.divide(1.0, 5.0e-324)
In other words, most functions that returns floats have an unmapped codomain and because of how floats work, and it is not simply a matter of checking if one of the inputs is equal to 0.0.

If Gleam wants to be consistent with division, all float operations would have to return a `Result` type (which I assume would have a direct impact in both performance and user convenience). Plus `let assert` provides a hatch for any function to raise too, and that includes matching on unmapped floats:

    let assert <<a:float>> = <<0x7FF0000000000000:64>>