very very good
very very good
// Division by zero is not an error
io.debug(3.14 /. 0.0)
It prints 0
Yuck. Division by zero is an unfortunate reality but basically nobody with mathematical background thinks that just defining x/0 = 0 is a good solution.
Often in numerical computing, getting an NaN or Inf is a blessing in that it’s a hint that your algorithm is numerically buggy, in the same way that a crash or a exception would indicate a program bug.
This approach is the numeric equivalent of a program continuing on after an undefined variable, just assuming it’s 0. That was tried by scripting languages in the 90s and these days most folks think it was a bad approach.
> 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...
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>>A problem that Gleam has here is that the Erlang runtime does not have NaN or Inf in its float type (or integer type for that matter). It could be represented with an atom, but that would require an atom and a float having the same type in Gleam, which is not something the type system can do (by design). The operator could, in theory, return a Result(Float, DivisionByZeroError), but that would make using it very inconvenient. Thus zero was chosen, and there is an equivalent function in the stdlib that returns a result instead, if you wish to check for division by zero.
Just fine mathematically, but Hillel does specify that he's not comfortable with the concept from a safety perspective. The whole piece is a defence against a particular type of criticism, but he leaves wide open the question of whether it's a good idea from a PL perspective.
I'm sure it doesn't work for everybody, but I never had a specific need to deal with zero in the division that didn't result with "actually let's count it as 0"
Imagine that you are running some A/B tests and you want to track conversions. If one of the experiments received 10 users and had 5 conversions, you want to show 50%. If it received 10 users and had no conversions, you will show 0%.
However, if it has received 0 users, while you could show zero conversions, the correct answer is to say that you don't know the conversion rate. Because maybe, if you had had 10 users, they could have all converted, and the rate would be 100%. You simply don't know.
Same logic applies over computing ROI, interest, velocity, etc.
In python for instance, the developer needs to be prepared to catch a divide by zero exception.
In gleam, the same consideration is required but the implementation will just differ.
I don't actually see an issue here. It's a potential gotcha, but once you are aware of this feature of the language, it's no different than any other.
> In gleam, the same consideration is required but the implementation will just differ.
These aren't remotely the same. If a developer fails to catch an exception or a NaN then the program either crashes or returns an obviously wrong result. If a developer fails to guard against a zero returned from division then they get a number out that's wrong in subtle ways that may not be obvious until the wrong numbers are already in use somehow.
The question isn't whether you can work around the error, it's how likely you are to notice that you screwed something up before it's too late.
In Python and languages with similar behavior, a division by 0 will immediately crash your program with a pretty stack trace, showing you exactly where the problem is and how the program got there.
In languages where division by 0 produces infinity, NaN, 0 or similar, your calculation just returns a nonsensical result.
Zero is even worse than inf or NaN, as you may not even realize that there was an error in the first place, as the result of your calculation is a number and not a strange-looking value.
Moreover, it’s actually pretty common for proof assistants to adopt the x/0 = 0 convention, as it turns a partial function into a total one! Having something like NaN or Inf is definitely a better solution in practice, but x/0 = 0 does have its merits!