New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1 % 0 is an intentional runtime exception #909

Closed
rtfeldman opened this Issue Sep 26, 2017 · 5 comments

Comments

Projects
None yet
6 participants
@rtfeldman
Member

rtfeldman commented Sep 26, 2017

This was a design decision from 2013 based on how Haskell did it, which predated Elm's No Runtime Exceptions design guideline.

Creating an issue for this just to track it in https://github.com/elm-lang/core/issues/377

According to IEEE:

Some operations of floating-point arithmetic are invalid, such as taking the square root of a negative number. The act of reaching an invalid result is called a floating-point exception. An exceptional result is represented by a special code called a NaN, for "Not a Number".

Since NaN is already an Elm value due to IEEE's influence on hardware design, it seems in line with how Elm's design goals have evolved to remove the following conditional throw in favor of letting JavaScript's % return NaN in the case of division by zero, which is the normal behavior of JS %.

https://github.com/elm-lang/core/blob/80bbcc901b748f2af250b92a6a3aa5b43a73edcf/src/Elm/Kernel/Basics.js#L23-L25

A counter-argument to this is that in a world where Elm compiled to Assembly, although it could trap SIGFPE from the processor (supported on Windows as well as on POSIX) for integer division by zero, floating-point division by zero is considered well-defined by IEEE to be Infinity. So there would have to be some runtime overhead to check for Infinity, and any runtime overhead on arithmetic operations has the potential to be multiplied by a massive quantity of operations.

Interestingly, in Rust, both x % 0 and x / 0 crash the program, indicating that generating an extra automatic comparison with 0 (in order to crash if detected) was considered a worthwhile cost to pay, even for a language with a primary design goal of "have no runtime overhead."

@process-bot

This comment has been minimized.

Show comment
Hide comment
@process-bot

process-bot Sep 26, 2017

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

process-bot commented Sep 26, 2017

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

@jvoigtlaender

This comment has been minimized.

Show comment
Hide comment
@jvoigtlaender

jvoigtlaender Sep 26, 2017

Contributor

Maybe worth referencing the "integer division by zero" item from https://github.com/elm-lang/core/issues/721 here. (https://github.com/elm-lang/core/issues/590)

Contributor

jvoigtlaender commented Sep 26, 2017

Maybe worth referencing the "integer division by zero" item from https://github.com/elm-lang/core/issues/721 here. (https://github.com/elm-lang/core/issues/590)

@gogocurtis

This comment has been minimized.

Show comment
Hide comment
@gogocurtis

gogocurtis Dec 20, 2017

I've noticed it is possible to crash the browser with code that is not called but does a divide by zero.

-- this will divide by zero when it is defined
unsafeFun =
    let
        start = 0
        end   = 3
        len   = List.length []
        indexes  = List.range start end |> List.map (\idx -> idx % len)
    in
        indexes

gogocurtis commented Dec 20, 2017

I've noticed it is possible to crash the browser with code that is not called but does a divide by zero.

-- this will divide by zero when it is defined
unsafeFun =
    let
        start = 0
        end   = 3
        len   = List.length []
        indexes  = List.range start end |> List.map (\idx -> idx % len)
    in
        indexes
@brian-carroll

This comment has been minimized.

Show comment
Hide comment
@brian-carroll

brian-carroll Dec 23, 2017

@gogocurtis that is actually not a function definition, it's a constant value definition.

If you're used to languages that have functions with no arguments, Elm doesn't have that. All functions have arguments. Anything that doesn't have arguments is a constant, whose value will be evaluated on startup.

If you want to define a value but delay evaluation until you need it, the usual way is to use the empty tuple () as the argument type of a function, and just ignore it in the function body. (Usually naming it "_")

brian-carroll commented Dec 23, 2017

@gogocurtis that is actually not a function definition, it's a constant value definition.

If you're used to languages that have functions with no arguments, Elm doesn't have that. All functions have arguments. Anything that doesn't have arguments is a constant, whose value will be evaluated on startup.

If you want to define a value but delay evaluation until you need it, the usual way is to use the empty tuple () as the argument type of a function, and just ignore it in the function body. (Usually naming it "_")

@evancz

This comment has been minimized.

Show comment
Hide comment
@evancz

evancz Mar 7, 2018

Member

Tracked in #377.

Member

evancz commented Mar 7, 2018

Tracked in #377.

@evancz evancz closed this Mar 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment