Hello,
I'm pretty sure this one popped up already before: Nim recognises =- as an operator and thus fails to compile default parameters that are assigned to negative numbers, unless a space is added after the =.
proc doSomething(msg="", opt=-1) =
echo msg, opt
This would be a compilation error unless a space is put before the -1 value of the default argument.
Would it make sense to slightly alter the parser to handle the above example correctly in the absence of operator =- defined in the current context? (I think =- used for an operator would introduce a hell lot of confusion, and under normal circumstances most likely would be a case of mistyping -=)
P.S. I recall we embedded Squirrel lang for one of our project, and it had an operator <-, so any tersely formatted condition like if (a<-10 || a>10) return would cause a compilation error, which, unless you know what to look for, you could stare at for quite some time before realising what's going on. This also reminds me of earlier C++ compilers not being able to parse Type1<Type2<Type3>> correctly without a space between the closing angular brackets.
It won't break the existing code when the operator is actually defined. I don't know about other people's sensibilities about it though, but I wouldn't override =- for anything that accepts an integer after it, as it would be a sure way to shoot yourself in the foot.
As for fixing, I guess, it can be fixed at a higher level than lexer? Earlier C++ failed to compile vector<vector<string>> due to the ambiguity with >>, but they fixed it, and it seems like not fixing it could've been defended in a similar manner, but the utility of preserving it would be marginal?
I think it is very confusing that =- fails to compile. I don't find the fact that it is not the recommended style a very convincing argument because it is still an allowed syntax).
Is there a compelling use case for supporting '=-' as an operator (as opposed to the usual '-=' ?)
That being said, IMO the biggest problem is the error message that you get:
Error: expected: ')', but got: '1'
It really is very unclear. I don't think I'd have been able to guess what the problem was (or at least it would take me a long while to understand it).
It is OK to not want to treat this as a special case, but I think the error should be changed to be much more useful and specific. For example:
Regarding the 'not recommended style', I understand the argument. It does shift the reasonable expectation hierarchy though by making an incredibly rare feature interfere with something I'd imagine many people would stumble into, especially those coming from Python. In Python it's the default style to skip spaces around = for default argument values.
Besides, in relation to what's recommended, I'd consider overriding =- to be a very strange design choice, in my opinion, certainly a lot more questionable than (statistically speaking) expecting a=-1 to work in a somewhat familiar looking programming syntax.
George.
The error messages that are the worst (and the hardest to improve, given the paucity of information at that stage) are, like this one, in the parser/lexer.
If x=-1 is outside of a formalParams, as in var x:int; x=-1 you get the clear, if frustrating:
Error: undeclared identifier: '=-'
I get and agree with the idea of reasoning from first principles, but the consequences of this particular rule are very unfortunate and affect even simpler expressions such as '2*-1' which _must be written as '2 * -1'. This makes nim a little weird compared to most languages in this fairly common area.
Also, thinking from first principles one could say that '=' is an operator and '-' is also an operator, so why is =- a single operator instead of two? Does the rule that an operator is the _longest sequence of valid 'operator characters' make more sense than the opposite rule? I realize that using a shortest sequence rule would result in another different set of problems (e.g. ++, +=, etc.) but my point is that choosing one rule over the other is a little arbitrary. The rule to distinguish ambiguous cases could be anything and still not break a 'from first principles' thinking.
You made I good point. It’s clear that the extreme “take the shortest” rule is worse than the current “take the longest” rule. However that does not mean that there aren’t any rules that are still simple yet solve this problem (or make it much more unlikely). For example, disallowing (unquoted) binary operators ending with a “-“ and maybe a “.” might work in most cases and still would be pretty simple to understand.
Anyway, we both agreed that the current error message can be improved. I wish more could be done but I guess that all languages have their quirks.
For example, disallowing (unquoted) binary operators ending with a “-“ and maybe a “.” might work in most cases and still would be pretty simple to understand.
Yeah, until somebody introduces a unary ~ operator and then =~ doesn't work but =- does and the usual "inconsistent!" complaint comes up. We cannot win this, the real solution here is to read the manual, which is precise and not overwhelming (I hope).
Or just work around the ambiguity:
proc doSomething(msg="", opt=(-1)) =
echo msg, opt
doSomething()