Replies: 15 comments 57 replies
-
Personally, I'm in favor of Option 2. I feel like it is a good signature to enforce, and we could make it not an overhead to the "lazy" users by adding some IDE hints to remove or add variables to the signature with one click. My second option would be "No Option" at the language level, but with good linting that points out you should have fully defined named actions as a good practice (i.e. "Add |
Beta Was this translation helpful? Give feedback.
-
In Option 2, shall we write
Alternatively, we could also assume that |
Beta Was this translation helpful? Give feedback.
-
I also like Option 2. As in my comment above, we can have the best of two worlds: |
Beta Was this translation helpful? Give feedback.
-
@Kukovec @shonfeder @rodrigo7491 @thpani @p-offtermatt I should have mentioned you before, what are your opinions on this, if any? |
Beta Was this translation helpful? Give feedback.
-
Edit: I misunderstood the original proposal, see #70 (comment). In favor of option 2 with implicit wildcard My previous post, for the record:
|
Beta Was this translation helpful? Give feedback.
-
I'm mostly in favor of (2), and if you want syntax simplifications you can just have |
Beta Was this translation helpful? Give feedback.
-
I like 2) the most, but dislike the syntactic sugar of having I'd also appreciate a way to group variables, for instance
For me, 1) has one major issue: when I want to add a new part to the spec, with a new variable that I want to change only in some new actions, I have to go back and change parts that are completely unrelated to this new variable. This can certainly be phrased as a benefit as well, since it forces me to go over the spec and actually see whether the new changes affect anything that I wrote before. |
Beta Was this translation helpful? Give feedback.
-
I tried to follow @gabrielamafra's comment above, but I'm thoroughly confused by now. A few questions for clarification: Let’s say we have an action Also, for option 2, would a definition
|
Beta Was this translation helpful? Give feedback.
-
Another thought: this screams "user study" at me. We can find a bunch of people and show them the code snippets above, maybe with a brief paragraph of description about what's declared inside My only concern is if this is an economical solution, but we might recycle it for further questions about the language design + tooling. |
Beta Was this translation helpful? Give feedback.
-
One relevant thread of prior discussion can be found at https://informalsystems.slack.com/archives/CU8E7J9LL/p1629983648002000, this also hits upon a syntax essentially equivalent to (2), and Andrey notes there that he also hit on essentially the same approach earlier https://informalsystems.slack.com/archives/CU8E7J9LL/p1630058228030600. The fact that three different people have been drawn to the same idea independently seems to say something about its intuitive appeal :) |
Beta Was this translation helpful? Give feedback.
-
This kicks around some ideas based on things that have come up in conversation, stuff suggested in #62 (comment) and earlier in this discussion, and from other things I've seen around. Note that all the concrete syntax suggested here is just for example, and what Perhaps we could consider an approach that unifies the mode system with the To start, suppose we get consolidate the 5 different expression-level keywords:
I think we're agreed that what we are currently calling "modes" can also be Instead of determining the effect by using a mix of different brackets, In particular, consider how it might look if we follow languages like So that
is read to say
Since state variables (memory regions) are super important for TLA, let's also Now, let's suppose we have the following kinds of effects:
Whenever the type is omitted, we can understand the value of the expression to I've also suggested a slight renaming trying to make the significance of the So, a pure operator from an def Foo(x: int): int = {
// ...
} A state predicate would need to specify the memory regions it can access. So def StutterOnNegativeX: Read['x] = {
x < 0
} An operator that read from the state and returns an int would need to specify def XPlusOne: Read['x]{int} = { 'x + 1 } An action would need to specify the memory regions it can update. But we can def Next: Update[*] = {
& 'y <- XPlusOne + 1
& StutterOnNegativeX
} Here's a sketch exploring how we might precisely describe higher order operators def HigherOrd(a, pureOp, readOp):
(T => U, U => Read[...'vars, 'x]{int}) => Read[...'vars, 'y] & Update['x] = {
& 'y < 19
& 'x <- readOp(pureOp(a)) + XPlusOne
}
Anything interesting in any of this to y'all? |
Beta Was this translation helpful? Give feedback.
-
I've stumbled upon an interesting case, so I'm posting it here for us to reflect. But first, to update the context: we already have a working effect system capable of preventing multiple updates of the same variable and ensuring disjunctions are balanced (all branches update the same set of variables) based on Shon's last comment (thanks Shon!). I noticed this definitions in a spec from Zach: MaybeUpdateBlock ==
\/ block' = block + 1
\/ UNCHANGED block Considering option 2, this is how I thought we could write the same definition in TNT:
or even
Both TNT versions are not terrible, but I do think they look worse than the TLA+ version, so it might be a case to pay attention to. My first thought is to introduce an operator that takes an expression
we could also consider adding I'm not confident that this is actually an issue, nor that my proposed operator is a good solution. I'd just like to register the idea and see what you guys think @konnov @Kukovec @shonfeder @rodrigo7491 @thpani |
Beta Was this translation helpful? Give feedback.
-
That an interesting observation. I have not thought about it. Both of your versions in Quint looks fine to me. We could introduce a constant |
Beta Was this translation helpful? Give feedback.
-
I have just found a simple workaround to keep the effects checker happy:
My idea was just to write an This actually makes me wonder, whether we want to place |
Beta Was this translation helpful? Give feedback.
-
I remember that @bugarela and myself were discussing another approach to the problem that is not documented here. Documenting it for completeness (also to get rid of my todo). We have been trying to figure out what is better: (1) Specifying which variables should be unchanged, or (2) specifying which variables should have assignments. Both (1) and (2) have various good use cases. Why don't we find a way to specify the both? Here is my proposal: introduce two operators: BranchesBefore we define the semantics of
Semantics of
|
Beta Was this translation helpful? Give feedback.
-
In a recent Quint meeting, I've discussed with Igor about three different ways we could handle
unchanged
in Quint. Some of the ideas we discussed were already suggested in the past, but I don't really know who suggested what. Let's recycle these ideas in this discussion and try to reach consensus.An important constraint I'm taking as a premise is that there is no perfect solution that requires no user definitions and can infer the expected behavior. To exemplify this, take the following action definition:
If the author's intention was to define stuttering steps over states where
x < 0
, a possibly expected behavior here would be to raise an error saying thaty
is assigned twice. If we give no resource for the user to specify a stuttering step, we lose the ability to point out this type of errors.Option 1 - Declare what is unchanged
The TLA+ way: make it so the user has to explicitly list all variables that are unchanged, either via an operator or with manual assignments (i.e.
x <- x
).Option 2 - Declare what is changed
Each action should declare which variables it changes, and we could use
*
for "changes all variables". This makes it easier to introduce implicitunchanged
statements for all the declared variables at each action as a conjunction.Option 3 - All action definitions fully define variables
This is implicit behavior that requires no typing from the user but relies on users reading the documentation. In this approach, it's like all actions are
action<*>
in Option 2, so we always introduceunchanged
statements at each action definition (that is, a named action).No Option
We could also choose to just introduce
unchanged
statements at theNext
action. In this case, a user could be explicit in a more verbose way if they want to:Beta Was this translation helpful? Give feedback.
All reactions