quint: Don't treat `{exp}` and `(exp)` as synonymous
The current language description makes curly brackets and parenthesis synonymous when wrapping expressions:
Every expression can be wrapped with
{
and}
. … Similar to{
and}
, you can always wrap an expression with(
and)
, e.g.,(1 + 3)
. It is up to you.
I think this introduces an unnecessary complication and redundancy into the syntax. I propose reserving {...}
for indicating special scopes, such as the patterns in a case
or the body of an operator, and only allow (...)
for grouping expressions.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 29 (29 by maintainers)
I like the separation of lambdas into pure- and effect-lambdas, but we then have to be consistent in the enforcement. For example, set map cannot take an action, so, for example,
S map { ... }
should never be allowed. You can only writeS map (x -> ...)
orS.map(x -> ...)
, omitting a set of parenthesis (i.e. notS.map( (x -> ...) )
. Same forexists
(but not guess), forall, filter, etc.Well, the TLA+ semantics is not different. But the distinction between the action mode and other modes is quite important. That’s what TLA+ puts under the rug. I want to make it visible and statically checkable.
I don’t know whether it holds for all TNT expressions, but one of my goals was to eliminate non-determinism in the non-action modes. Non-determinism should be very well-isolated, because it is a side effect 😃
I don’t find this to be a perspicuous expression of the logic. IMO, this seems convoluted and hard to read, given what it does.
The conditional is still an expression, that’s right. In most cases, some people might want to write
x' = 1
and apalache would treat that as an expression, no side effects. Btw, that would be impossible in TNT 😃My inclination is to say that our question should be: are the branches of a conditional and the body of an operator just expressions like any other?
If so, we can just pick one form of brackets for grouping expressions, and use that consistently. (For
if
, this becomes cleaner imo if we useif exp then exp else exp
(which is similar to may existing languages, including TLA+).Examples:
Otherwise, if these scopes are meaningfully different from regular expressions, then we can have a principled justification for using different scope delimiters, like we already do for modules. Then we can explain why use of
{...}
would have a principled, non-ambiguous use in these two cases, while still not overloading it to do double duty.To make the reason for my concern more concrete, iiuc, this following will valid if we allow
{...}
and(...)
to by synonymous (except when they aren’t, for module scope and delimiting operator arguments):While this could just be left up to coding style, I don’t understand what would justify inviting this kind of chaos! 😄