14 ms·
My problem with "1/0 = 0" is that it's essentially masking what's almost always a bug in your program. If you have a program that's performing divide-by-zeroes,
by whack 8y ago
My problem with "1/0 = 0" is that it's essentially masking what's almost always a bug in your program. If you have a program that's performing divide-by-zeroes, that's almost surely something you did not intend for. It's a corner case that you failed to anticipate and plan for. And because you didn't plan for it, whatever result you get for 1/0 is almost surely a result that you wouldn't want to have returned to the user.
When encountering such unanticipated corner cases, it's almost always better to throw an error. That prevents any further data/state corruption from happening. It prevents your user from getting back a bad result which she thinks she can trust and rely on. It highlights the problem very clearly, so that you know you have a problem, and that you have to fix it. Simply returning a 0 does the exact opposite.
If you're one of the 0.1% who did anticipate all this, and correctly intended for your program to treat 1/0 as 0, then just check for this case explicitly and make it behave the way you wanted. The authors of pony are welcome to design their language any way they want. But in this case, they are hurting their users far more than they are helping.
- avip 8y agoIt’s common for 1/0 = 0 to be exactly what you want. Array average for example. That said raising exception would be the only consistent behavior if a language supports that.
- magicalhippo 8y agoAnd in other cases you really do want the infinities. For example fast ray-AABB tests like https://tavianator.com/fast-branchless-raybounding-box-intersections/ https://tavianator.com/fast-branchless-raybounding-box-inter...
- drb91 8y agoCommon compared to what? Taking an average of an empty array is nonsensical.
- mlthoughts2018 8y agoI disagree. It’s similar to computing NaN-mean or NaN-sum for an array of all NaN values (which returns 0). Let’s say some program calculates the mean of an array and then adds that mean to some accumulator. For purposes of updating the accumulator, the mean of an empty array is perfectly well-defined: it should add nothing to the accumulator (add 0). This might be a major operating requirement for the mean function, such that rather than guarding or pattern-matching on an empty array and handling a failure is far worse than having a better 0-length convention. Consider the difference between the “head” function of some List type, which has to either raise an exception or wrap the return value in some Maybe structure, because it’s literally not definable, vs the “length” function which has an obvious natural definition for empty arrays that is often highly preferred to some design where length(empty_list) throws an exception and everyone has to handle it in little bits of custom code to specify 0. To me this topic is all about usability and not about some parochial claim that some operation is nonsensical.
- drb91 8y ago> It’s similar to computing NaN-mean or NaN-sum for an array of all NaN values (which returns 0). Why would you want to do this rather than validating understanding of the data before computing on this? > For purposes of updating the accumulator, the mean of an empty array is perfectly well-defined: it should add nothing to the acculator (add 0). That's not a mean, though, that's a quirk of how you decide to (incorrectly) compute a mean. What's the point of such a program? It should refuse to compute when it's given no values--that's clearly a category error. Otherwise, you're not using a mean, you're using a mean-or-0-when-lacking-a-mean. Might as well not call it a mean at all so other people can read your code. Yes, this is pedantic, but this kind of subtle changing meaning of terms is exactly what leads to bugs. Name your functions accurately.
- mlthoughts2018 8y agoFrom your response I can tell you don’t do much numerical linear algebra work. Consider needs to vectorize a large column-wise mean calculation across columns of a large data matrix (where NaN values are sparse but appreciable). The NaNs might be perfectly reasonable, expected pieces of data, but you still want to understand the distribution of the non-NaN data, and adding extra work to filter it out first might be hugely costly, or even actually wrong depending on what other operations the NaN data is planned to be passed to and how those operations natively handle NaN. And simple columnar summary stats are just the tip of the iceberg. It gets much more complicated. By no means is the solution of “diagnose why there are NaNs ahead of time and preprocess them accordingly” even remotely realistic in most use cases. This is why libraries like pandas, numpy and scipy for instance provide specific nan-ignoring functions or function parameters.
- kazinator 8y agoIt is not valid to extrapolate an average of 0 from no data at all. For example, if we examine a sample of zero elephants, then we end up estimating the average elephantine mass as being zero. This shows to be wildly off as soon as we upgrade our statistical wherewithal to work with a sample size of one. A center of mass is a kind of average. If we have an empty object made of no particles of matter at all, can we arbitrarily pin its center of mass to the (0, 0, 0) origin of the coordinate system we are using?
- NickNameNick 8y agoThis is probably beside the point, but shouldn't the center-of-mass of a massless object be everywhere simultaneously? With no reason to prefer any location, over any other?
- Retra 8y agoThe center of mass of a massless object makes as much as "everywhere" being a location of anything.
- dahart 8y ago> It’s common for 1/0 = 0 to be exactly what you want. Array average for example. Wouldn’t that be a (potentially very different) case of 0/0? If there are 0 elements, you wouldn’t have a nonzero numerator, right?
- IshKebab 8y agoThe mean of an empty array isn't zero though.
- fasquoika 8y agoThe real issue is that Pony doesn't have the concept of an unrecoverable error. All exceptions in Pony are checked, but sometimes if an error happens there's nothing your program can do and it should just crash. Edit: Although Pony claims that programs should never crash, the language designers clearly understand the pragmatism of an unrecoverable error because it happens on OOM and stack overflow
- draw_down 8y agoOK but that doesn't have a lot to do with what TFA is actually talking about.
- bunderbunder 8y agoI almost want two different division operations: One where 1/0 = 0, exclusively for use in progress bars and stuff like that, and another one for everything else. Because frequently division by zero indicates a bug. But similarly frequently, I end up crapping out annoying little bits of code like if (foo == 0): return 0 else: return bar / foo
- spooneybarger 8y agoWe will be introducing two sets of integer math operators in Pony. The current which are non-partial and can over/underflow + division by zero == 0 AND new ones that will be partial functions that cause an error on under/overflow and division by zero.
- gopalv 8y ago> new ones that will be partial functions that cause an error on under/overflow and division by zero. A "strict" mode is usually always an afterthought once we have errors & people run it in strict mode and facepalm. One of the first "utilities" I wrote for PHP was something called "pecl/scream", which turned off all the "unchecked" operations across the whole VM. And in general, this works out poorly for code quality.
- rhencke 8y agoPony is not 1.0 yet. The language is still malleable.
- jeremyjh 8y agoThere is no golden path here. Checked exceptions for division would make a lot of Pony code objectively worse. Unchecked exceptions are great for PHP, Haskell, Rust or Go, but Pony is trying to do something different - to literally make it impossible to panic in an operation without describing that in the type system. The ergonomics of divide by zero in this context are absolutely debatable, not an issue to dismiss out-of-hand.
- weberc2 8y agoIs this different than integer division or integer over/underflow? I mean, besides that the integer behavior is status quo and 1/0 is not. Genuine question.
- dllthomas 8y agoInteger over/underflow is arguably less arbitrary. Sometimes Z mod 2^k is really where you want to be working, and the rest of the time at least it's the fastest answer. Whether that's enough of a justification to be a difference? shrug
- madrox 8y agoYou're absolutely right. Not only that, but it's impossible to distinguish a bad result like 1/0 vs a good result like 0/1. Even Javascript is better with "NaN"
- jwilk 8y agoTo clarify, in Javascript 1/0 is Infinity, not NaN.
- eggnet 8y agoYou are correct. But it really should be NaN, since 1/ε is positive infinity, whereas 1/-ε is negative infinity. Oh well :)
- Jach 8y agoJS just assumes the limit direction for you, so 1/0 is Infinity, but -1/0 is -Infinity. 0/0 at least is correctly NaN. (Edit: And I just verified against my memory, Matlab (or at least Octave) does the same thing. While Matlab might get characterized as being for the ivory tower, at least it's had a long history of being used for practical math applications within the tower. Edit2: And anyway this is the defined behavior for IEEE floats. Men of industry use industrial standards. :))
- lightgreen 8y agoMoreover, 1/-0 is -Infinity. IEEE float has two zeros, positive and negative.
- mehrdadn 8y agoNope, I'd disagree. Zero isn't an approximation of some epsilon, it's really just zero. It makes sense for the output sign to match the input sign.
- gowld 8y agoWhat is the sign of 0? It's 0.
- wutbrodo 8y ago> But in this case, they are hurting their users far more than they are helping. How could you possibly make an assertion like this without knowing why they made said choice[1]? Per the article, they didn't do it for fun, or to avoid exceptions (as you point out, more like defer exceptions). FTA: > As I understand it, it’s because Pony forces you to handle all partial functions. Defining 1/0 is a “lesser evil” consequence of that. Do you know enough about Pony's language design and decision process to support your claim that this decision (and all its second-order consequences) is hurting users far more than helping them? [1] On the off chance that you are familiar with the tradeoffs Pony made and do know what you're talking about: care to clarify?
- spooneybarger 8y agoHi I'm on the Pony core team and spent some time explaining the reasoning to Hillel. He hasn't written any Pony but I did walk him through how we ended up where we currently are. I will be writing up a post about why we made this decision.
- Veedrac 8y agoMy comment from when this came up on Reddit, slightly edited for context: `/`-by-0 is just an operation and it tautologically has the semantics assigned to it. The question is whether the specific behaviour will cause bugs, and on glance that doesn't sound like it would be the case. Principally, division is normally (best guess) used in cases where the divisor obviously cannot be zero; cases like division by constants are very common, for example. The second most common usage (also best guess) is to extract a property from an aggregate, like `average = sum / count` or `elem_size = total_size / count`. In these cases the result is either a seemingly sane default (`average = 0` with no elements, `matrix_width = 0` when zero-height) or a value that is never used (eg. `elem_size` only ever used inside a loop iterated zero times). It seems unlikely to me that `/` being a natural extension of division that includes division by zero would be nontrivially error-prone. Even when it does go wrong, Pony is strongly actor-based, has no shared mutability and permits no unhandled cascading failures, so such an event would very likely be gracefully handled anyway, since even mere indexing requires visible error paths. This nothing-ever-fails aspect to Pony is fairly unique (Haskell and Rust are well known for harsh compilers, but by no means avoid throwing entirely), but it gives a lot more passive safety here. This honestly doesn't seem like a bad choice to me.
- innagadadavida 8y agoWhat happens for 0 / 0? Is this also 0?
- taneq 8y agoIt's extra zero.
- nwmcsween 8y agoinf 0
- spacehunt 8y agoIs this the same as 0 * 1 / 0?
- innocentoldguy 8y ago
- elwell 8y agoWhat the world really needs: "1/0 = 0" in production build, "1/0 throws error" in development build...
- glitchc 8y agoIt happens in scientific computing with zero bounded signals fairly regularly. Sometimes values hover close enough to zero that the computation results in a/0. It's not desired but the only alternative is a guard that invariably adds a performance penalty. There are other ways around it, such as normalization, but they're not trivial depending on the problem and can actually add other sources of bugs/errors. I understand the author's intent even though I disagree with the result.
- jibal 8y ago1/a when a is close to zero is very large. 1/0 == 0 violates the limit and is just bad math.
- WalterBright 8y agoAn issue with D that has repeatedly engendered heated debate is what should happen when a programming bug is detected at runtime. The two camps are: 1. The program should "soldier on" if it can. 2. The program should go immediately to jail, it must not pass Go, and must not collect $200. I'm solidly in the latter camp. If a program has entered a state unanticipated by the programmer, then there is no way to know how it entered that state (until it is debugged), and hence no way to know what the program might do next (such as load malware). 1/0 is a bug, and the program should immediately halt.
- skrebbel 8y agoGreat analysis! I think that summarizes a lot of dev arguments. That said, Erlang appears to agree with both camps. If an error occurs, the _process_ immediately crashes (not OS process, it's Erlang Kingo for an actor or a green thread), but the _program_ soldiers on as if nothing happened. The idea behind the design, I believe, is that programmer errors are unavoidable, but that eg a bug in some edge case triggered by uncommon data shouldn't crash the entire server. I don't know much about Pony, but given that it is also actor based, I'd imagine this would be a great opportunity to crash early and eagerly. It gives you all the advantages of catching a bug early while not crippling a production app under what might be a pretty low-impact, low-frequency bug.
- electrum 8y agoJava has essentially the same behavior with threads. If an error occurs in a thread, it will throw an exception that will terminate the thread if uncaught. Other threads are not directly affected. This is typically what you want as threads are usually independent of each other, often processing an isolated request, which may encounter a bug due to bad data or other conditions. Contrast this to languages like C++, where the usual behavior is to segfault and crash the process. Special care must be taken if threads are manipulating shared data structures, especially inside a "critical section" where the data structure invariants must be maintained. This is why automatically terminating the JVM when OutOfMemoryError occurs is a best practice, as code is often not paranoid enough to handle it.
- Fomite 8y agoYep. Having had a couple divide-by-zero errors in a complicated simulation, I'm immensely grateful that it fails hard.
- brobdingnagians 8y agoTotally agree, in a mathematical proof you wouldn't ignore the edge case just because you think it might work the same way it has for some of your other proofs. It would invalidate everytihng, and in sequential processing, you could really mess up some of the data with one iteration with a 1/0 assumption that completely changes every iteration after it. Bad news.
- rzwitserloot 8y agoThe authors covers this at the end: [1] The author has a dislike of the notion that 1/0 = 0 in a programming language. The author identifies this as a personal preference; I'm sure that preference is based on falsiable notions, but the author doesn't elaborate. The author _DOES_ elaborate their motivation for writing the post: The post debunks the notion that 1/0 = 0 is 'bad math'. [2] Pony chose 1/0 = 0 because the language of Pony is set up to enforce the coder to complete all functions; if you go with the strict definition of division, which is an operation which has no definition if the second operand is 0, it's not complete anymore. I agree with your sentiment; this feels like the wrong answer, but it's definitely not as simple as just saying: Why don't the pony folks redefine things such that dividing by 0 raises some sort of error condition?
- jejones3141 8y agoDoes Pony have some analogous dodge for logarithms and square roots of reals, or for the gamma function?
- jack9 8y ago> If you have a program that's performing divide-by-zeroes, that's almost surely something you did not intend for It's such a common case to consider, I don't think that's compelling. Knowing that a division by zero throws an exception or casts to zero, is similarly considered. > they are hurting their users far more than they are helping. There's no evidence of this.