lobster
lobster copied to clipboard
Confusing error when there's space between for and opening brace
I'm following through the Shooter tutorial. It's very nicely done, thank you!
However, I've spent 5-10 minutes figuring why Lobster fails when there's space between for
and (
. I found the error message to be very confusing:
game.lobster(44): error: missing arg to builtin function: for
![image](https://user-images.githubusercontent.com/510678/66762236-46bca880-eeae-11e9-8735-611960da1b38.png)
I've even managed to make the same mistake in gl_circle
call, but the error message was totally different, and similarly confusing:
game.lobster(48): error: ) expected, found: ,
![image](https://user-images.githubusercontent.com/510678/66762596-f98d0680-eeae-11e9-89d0-d744e48b57fc.png)
Yes, that is unfortunate. It uses spacing in this case to distinguish between a regular function call, and a parentheses-less call that uses bracketing for precedence. For example, f (1 + 2) * 3
applies f
to the whole expression (no parens for the call), but f(1+ 2) * 3
applies *
to the result of the function call.
But yes, this makes for confusing errors. The question is, can this be fixed by special purpose error handling, better docs, or is deciding based on spacing just generally a bad idea (yes, it probably is). It's hard to remove them though, since parens-less calls are essential for making control structures look control-structury.
Opinions welcome.
I don't have an opinion whether "deciding based on spacing" is a bad idea. Don't know enough about the language.
However, I wonder if Lobster could ban some_function (
sequence altogether. Let's say I've written:
f (1 + 2) * 3
What was my intent? It could be:
- I've made a typo. I actually meant
f(1 + 2) * 3
. - I really wanted to apply
f
to the whole expression. In this case I could rewrite it asf((1 + 2) * 3)
.
The error for f (1 + 2) * 3
could be something like:
game.lobster(48): error: space before (, did you mean `f(1 + 2) * 3`?
I've searched for it in the Lobster repo: ag '[a-z] \(' tests/ modules/ samples/
Assuming you agree to disallow some_function (
sequence, in almost all of the examples you could either drop extra braces, or remove the space.
The only places I found where you have to add extra braces were the following:
assert (test_namespace_g {}).x == 1
assert (if manhattan(xy { 1, 1 }): xy { 1, 2 } else: xy { 3, 4 }).y == 2
assert (coroutine_for(coroutine refcoro(borrow)): assert(_ + "_" is string)) == "D"
assert (assert parse_data(typeof [bool], "[true]"))[0] == true
After the change:
assert((test_namespace_g {}).x == 1)
assert((if manhattan(xy { 1, 1 }): xy { 1, 2 } else: xy { 3, 4 }).y == 2)
assert((coroutine_for(coroutine refcoro(borrow)): assert(_ + "_" is string)) == "D")
assert((assert parse_data(typeof [bool], "[true]"))[0] == true)
Lobster's current parsing is so generic, that even if
, for
and while
are parsed as function calls. They have the same syntax as any other functions that take lambda arguments.. the point being that your own functions are on equal footing.
But that does stress that situation. if
with your proposal now can either be:
if 1 + 2 < 3:
But now if for whatever reason I need to bracket 1 + 2
, I need two sets of brackets, and spacing that is not familiar (it may take new users of Lobster a while to realize if
is really a function call):
if((1 + 2) < 3):
Whereas with the current syntax, I can still do:
if (1 + 2) < 3:
One other solution is to simply stop treating the parsing of if
(and for
/ while
) as exactly the same as any other function call. This would be less elegant, but it would remove a bunch of warts from the function call parsing that were introduced just to make if
look Python-esque. Like you say, most actual function calls can deal with needing ((
since it doesn't happen that frequently.
But of course, the problem just shifts, because if I special case these 3, then someone is going to make the same mistake with e.g. map
where they expect it to behave similary to for
, except then maybe it doesn't.
One way I can think of getting rid of the significant space is to require functions to declare that they take an argument without brackets... but that also sounds kinda kludgy.
maybe add a pipe operator, similiar to haskell's $
? just a small thought
@argvsc47 that may be nice to add, but does not relate to the discussion above afaik?
Checking 4 years later. Space after for
is now allowed, very nice!
@aardappel, do you remember what change fixed it?
What changed since my last comment is that if
, for
and while
are now parsed independently from function calls, which will have fixed this issue for them.
It is still a problem in general, if you make a custom for loop myfor
, it will run into your original errors if you put a space after it.. but I guess that doesn't happen as often.