Skip to content
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

- and + behave inconsistently #2329

Open
Golden-Phy opened this issue May 26, 2024 · 6 comments
Open

- and + behave inconsistently #2329

Golden-Phy opened this issue May 26, 2024 · 6 comments

Comments

@Golden-Phy
Copy link

Golden-Phy commented May 26, 2024

Quick Summary: Miss-formatting of an infix subtraction can lead to an interesting phenomena, where the first operand is interpreted as a function and the second as an argument, leading to the compiler saying that a number doesn't take that many arguments. Doing the same with + works fine though.
My assumption is that - is treated as unary operator, something that the + operator apparently doesn't support.

SSCCE

module Main exposing (..)

import Browser
import Html exposing (Html, div, text)

-- MAIN
main =
  Browser.sandbox { init = init, update = update, view = view }

-- UPDATE
update : () -> Model -> Model
update _ model =
  model

-- MODEL
type alias Model = ()

init : Model
init = ()

-- VIEW
view : Model -> Html ()
view model =
    div [] [text (String.fromInt(1 -1))]
-- Example without whitespaces
--    div [] [text (String.fromInt(1-1))]
--    div [] [text (String.fromInt(1 - 1))]
--    div [] [text (String.fromInt(1 +1))]
-- Example illustrating the interpretation of the compiler (at least for me)
--    div [] [text (String.fromInt(1 -1 * 2))]
  • Elm: Playground on https://elm-lang.org/try as of 26/5/2024
  • Browser: Mozilla Firefox for Fedora 123.0 (64)
  • Operating System: Fedora 39

Additional Details

Compiler output:

TOO MANY ARGS
Jump to problem
This value is not a function, but it was given 1 argument.

24|     div [] [text (String.fromInt(1 -1))]

                                     ^
Are there any missing commas? Or missing parentheses?
Copy link

Thanks for reporting this! To set expectations:

  • Issues are reviewed in batches, so it can take some time to get a response.
  • Ask questions in a community forum. You will get an answer quicker that way!
  • If you experience something similar, open a new issue. We like duplicates.

Finally, please be patient with the core team. They are trying their best with limited resources.

@nopria
Copy link

nopria commented Jun 5, 2024

I was thinking about adopting ELM for a project but the fact that basic issues like this one are not likely to be solved any time soon leads me to look for an alternative.

@qrzychu
Copy link

qrzychu commented Dec 4, 2024

@nopria I am not a maintainer, but is the above really a blocking issue? just add space and it works.

I know it's technically a workaround, but it's fairly straghtforward.

It's not like it requires creating === to fix the real problem.

I guess it's just that +1 is an operator (1 |> (+)), while -1 is a number literal, which are logical IMO. Once you know that, you can just hop on and write your code. Fixing this is either treating -1 as 1 |> (-) everywhere or having a special case for just negative numbers.

Or you can add a space.

Aslo, what alternative did you land on?

@GordonBGood
Copy link

GordonBGood commented Jan 20, 2025

My assumption is that - is treated as unary operator, something that the + operator apparently doesn't support.

Elm works a little differently than some other languages you may have used: When the dash immediately precedes the number (without spaces), the parser picks up the minus symbol and negates the following number, with the intervening space(s) the dash is parsed as a binary infix operator.

The plus symbol is always treated as a binary operator so +42 by itself doesn't work as literal at all as in order to be valid Elm code it would have to be written as an infix expression <somenumber>+42, and in order to be written as a function would need to be written as (+)42 in order become a single parameter function.

Other comparable languages aren't that ideal either in this regard: Haskell and PureScript require parentheses around the unary operator and the number in order to cause the unary negate to become effective. This isn't very nice either and requires more typing to put in the enclosing parenthesis when the unary negate is used.

EDIT_ADD1: F#/OCaml work exactly as Elm does with about the same error message...

This isn't really an issue and just requires that one learns the Elm syntax, although perhaps the error message could be improved to suggest that there is a missing space between the dash and the number...

EDIT_ADD2: However, I suppose it could be cleaner by having the compiler inject a + operator between the two when this particular error comes up and see if that fixes the problem, although I would worry that it would introduce other edge cases further down the compiling pipelines...

@Golden-Phy
Copy link
Author

I have updated the SSCCE to include an example of it compiling without whitespaces, I apparently forgot to do so initially.

Elm works a little differently than some other languages you may have used: When the dash immediately precedes the number (without spaces), the parser picks up the minus symbol and negates the following number, with the intervening space(s) the dash is parsed as a binary infix operator.

So, is the assumption wrong? Are you trying to say that it parses the dash as part of a numeric literal or am I completetly lost?
At any rate, my issue is that 1 +1 is valid syntax and a clean compile, while 1 -1 will just give a cryptic error. Of course I can 'just know' that, but I would prefer to be stopped from using ambigious syntax by a good error.
My guess is that this also points to a deeper issue with whitespace being used as optional formatting, as is common, and also for function invocation, with no reserved separator beetween 'arguments'.

@GordonBGood
Copy link

So, is the assumption wrong? Are you trying to say that it parses the dash as part of a numeric literal or am I completetly lost?

Yes, Elm parses the dash and if it parses a number literal immediately following, applied the negation to the number, otherwise it parses it as the subtraction binary infix operator.

My guess is that this also points to a deeper issue with whitespace being used as optional formatting, as is common, and also for function invocation, with no reserved separator beetween 'arguments'.

Again, you are correct that the issue is related to curried function application just using separated spaces for argument application, which is the only other way it has to parse this. So the simple two ways of handling it are this way which Elm borrowed from F#, or the Haskell way where it is often necessary to place parenthesis around negated literals to make it compile.

Python doesn't have this particular problem because function application is by using parenthesis and comma separators; however, one would have a different problem if one forgot to type a comma separator in a tuple literal or a comma separator between function arguments, which might still be valid code since many Python functions are variadic or have default values so the full set of arguments doesn't have to be supplied, and the error could propagate to who-knows-where to show up at runtime due to dynamic typing...

As I said, there might be another somewhat more complex way to inject a plus operator between the arguments when it detects this argument, which would fix it but one would have to go through a whole test routine to be sure it didn't mess up something else. One possible ambiguity I can think of is that if one missed typing a comma of a tuple of literal numbers, injecting the plus operator would turn it from being a two tuple into just a single expression inside parenthesis, which would likely cause a problem somewhere else in the code that expected a tuple... Just one example of a possible problem with this "solution"...

At some point one just has to learn the usual error in writing code that Elm can't handle and will need to be corrected, but at least the Elm compiler is correctly identifying the location of the problem; the only thing its missing in the error message is that, not only could it be a tuple with a comma or improperly grouped with parenthesis, but that it could also be a problem with spacing of a subtraction operator...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants