Open spoerri opened 1 year ago
There being a second syntax to execute code (parentheses) is also a little confusing, and it doesn't feel as if one is just sugar for the other.
Having parentheses around method invocation automatically inserts a period so that (object Method.)
can be written as (object Method)
. There's nothing really that special about parentheses except for the fact that it allows us to omit the period without introducing ambiguity.
Would you consider going entirely with the parentheses syntax, and jettisoning the period syntax?
I have considered it. The way I see it, there are three options:
I am not a fan of option number 3 because then we also need to introduce more precedence and associativity rules.
Options 1 and 2 both have sort of opposite pros and cons. Parens clutter up code, especially since almost everything(if/loops/switch/etc) is done through a method call, but they are excellent at making clear exactly how the grouping works. Periods are the opposite - they add almost no clutter but they require a little bit of mental gymnastics to figure out what is happening. From my experience, mixing the two creates the most readable code - you can be concise when grouping is obvious and verbose when necessary. This does give qdbp developers the ability to write really bad code with either too many parens or too many periods. Maybe some sort of linter is the solution?
Is it correct that, when I see a ".", I should scan back in the code to find the closest preceding capitalized token or "!" or operator, skipping over any intervening nesting blocks of [] or () or {}, and that's what the "." is actually causing to run?
That is more or less correct with the small caveat that you should also skip over intervening capitalized token/symbol and period pairs. For example,
object1 Method arg1: object2 Method..
gets grouped like:
(object1 Method arg1: (object2 Method.).)
The example you provided was correct
Presumably qdbp's support for variables would save it from parentheses hell.
I'm not sure it would. Lisps have variables and they still have parentheses hell.
Some c-style-syntax languages also don't like complicated precedence, and force use of parentheses. E.g. a + b c won't compile (though of course a b + c also won't). Could you do something similar by default, and also somehow allow the method definition to customize precedence for the sake of extensibility? For example, if somebody is implementing their own control flow design using prototype methods, they'll know how its precedence should work, and not want to rely on users to place periods properly.
Lisps have variables
Yes, I guess I was hoping that more idiomatic variables would make a difference, but it's just hope. :)
Sorry for the late reply.
I think my problem with that is the complexity it introduces. From the implementation side, the language will no longer be context free. And I think when people start using libraries that have a bunch of custom precedences, they will have a bunch to learn. What if two libraries define different precedences for the same operator?
The idea of having operators but force users to put parents for ambiguous expressions is probably how I'd do it if I were to add them. But I feel like it would just lead to the parentheses problem.
Not at all. OK, brainstorming: how about by default, Methods are always invoked, without parens and without period.
Then parens could just be used for grouping when right associativity isn't enough.
If I've got it right, the code in the Tutorial/Overview would be fine without any periods except for three cases:
four := (prototype Method3) Method2 arg1: 4
safe_divide := {a b|
(b = 0)
True? [#Error{}]
False? [#Ok a / b]
}
intlist := (empty_list Append 3) Append 2
You still have to scan back, but at least there's only one syntax to control evaluation order instead of two. And of course, it doesn't do anything to help people who are surprised by the evaluation order of a * b + c.
That actually does look a lot cleaner.
I am playing with the parser right now, and I can't seem to find a way to make a grammar like that unambiguous. But let me play with it a bit more and get back to you.
You are right though, the arithmetic case now can become confusing. To be honest, I'm not sure there is a good solution to this that checks every box(if there was, it probably would have been found by now).
Maybe worth a separate github issue or two, but i can think of a some things that would help if you're committed to supporting operator overloading, and willing to stomach a little extra complexity...
a + b + c
shouldn't have to be parenthesized...10 - 6 - 3
to be equal to 7. It would kind of suck to special case them...
Suggestion: make all operators left associativeEven with that exception, there'd still be a a lot parentheses required... Suggestion: Support just three different precedences, for categories of operators that would not otherwise reasonably type-check. From low to high:
E.g. a && b + c < d
only makes sense as a && ((b + c) < d)
, at least without coercions or "truthiness".
(All the above is for methody operators. () [] {} : @ # ? would all be unaffected.)
Though the above logic obviously doesn't match the high standard of simplicity that you have set for qdbp so far, imho it'd be a small price to pay for syntax that so closely matches people's intuition for normal notation. Most people wouldn't even need to read the documentation. 😄
With the period syntax, it's a little hard to see what's getting executed...
Is it correct that, when I see a ".", I should scan back in the code to find the closest preceding capitalized token or "!" or operator, skipping over any intervening nesting blocks of [] or () or {}, and that's what the "." is actually causing to run?
Is there a way to get something like the clarity of mainstream programming languages on this?
There being a second syntax to execute code (parentheses) is also a little confusing, and it doesn't feel as if one is just sugar for the other. Would you consider going entirely with the parentheses syntax, and jettisoning the period syntax? It's very lispy, and imho qdbp could do worse than to continue the lisp tradition. Presumably qdbp's support for variables would save it from parentheses hell. Perhaps the parentheses syntax could be made slightly more complicated/powerful to support things like (a + b + c + d)