Hacker News new | ask | show | jobs
by prerok 734 days ago
Define "better language". The duck typed languages all suffer the same problem.

Even in Go we had a stupid problem where default json deserializer creates floats (when deserialized into any) and the number was high enough int64 where it lost precision.

I mean, we can go at it all night long what pitfalls await in what language. Perhaps Rust is safest with its own pitfalls where you just can't do it safely (looking at you BST and use of Arc).

Programming is full of such traps and only inexperienced engineers in a language would make such a mistake. This includes engineers with 20+ years of 1 year experience.

3 comments

In this case, a language that doesn't support automatic numeric type conversions. For instance, in Swift, 1 / FRAMERATE would give you integer division if FRAMERATE was an Int, or Double/Float division if FRAMERATE was a float, as the 1 literal would be inferred to a compatible type for / if one existed. You would never see Int / Float, or an implicit conversion between numeric types.
Never worked with Swift before, but this checks out: https://swiftfiddle.com/mt5uptmbynbt7bi4jot7m5laum

Careful though, if you don't have :Float on ts it still gives 0.

I don't understand the point of both replies... my point was that integer based division is preferred in all languages and the floating point must be somehow "forced" that one operand is float.

The post I was replying to mentions that this sort of problem does not exist in "better languages" but my point was that it does.

The problem here is that the code assigns an integer (result of division) to a float which is implicit "upgrade" in languages like C and C++ and required to be explicit in newer languages like Golang and Rust.

My point, which I seem to have failed to make, is that careless programmers would (and do!) make a silly thing like:

v := float64(operand1 / operand2)

just to satisfy the compiler error.

A common mistake for junior programmers but unforgivable (for some interpretations of unforgivable :) ) one for a senior.

> integer based division is preferred in all languages

What does this even mean?

First of all, several languages have distinct "integer divison" and "floating point division" operators, so there's no sense in which integer is "preferred" in those languages, they're unrelated operations.

Even allowing for your ignorance of such languages many modern languages do not have untyped constants, they're an attractive nuisance. If you don't have untyped constants then even if you're relying on implicit typing for constants (which I also don't like) you trip a mistake in the original expression anyway which is now unalike.

This mistake only occurs in a language with all of:

1. A single division operator despite two distinct operations

2. Untyped constants

3. "Promotion" so that type mismatches just do something unexpected and compile anyway.

So you would have different, say, distinct division operators for each of u8, u16, u32, u64, u128 and their signed variant, for each floating point type, complex numbers (and all their underlying variants), quaternions, etc? You might quickly run out of operator soup.
How did you get to this very strange understanding from what I wrote ?

We have two arguably distinct operations so we might want two operators, but you have instead invented a plethora, seeming to understand that somehow the operators ought to depend on the type, which is part of the original mistake.

(5 // 2 == 2) whereas (5 / 2 == 2.5) those are two distinct operations

In many places Rust for example chooses to provide multiple operations but to only grant the most C-like operation an operator, e.g. (-15_i32).div_euclid(2) is -8 that's Euclidean division but (-15_i32) / (2) is -7 as you'd likely expect in C

Or just use 1.0, which can only be a Float literal.
Python (3) gets this right. Integer division is a separate operator: // vs /.
“only inexperienced engineers in a language would make such a mistake” — famous last words…