Pointwise effects¶
When an action modifies the value of a mutable field, one must usually specify how one part of the field is changed by the action, and how another part is left unchanged (as seen in the Behavioral modeling chapter, this part is called a frame condition). For instance, the action share
associates a new sharing token t
to file f
, but other files are left unchanged by this operation.
pred share [f : File, t : Token] {
f in uploaded - trashed // guard
historically t not in File.shared // guard
shared' = shared + f->t // effect on shared
uploaded' = uploaded // no effect on uploaded
trashed' = trashed // no effect on trashed
}
In the specification above, the complete effect on relation shared
, that is the modification part and the frame condition, is specified all at once by saying how the whole field, viewed as a binary relation, is to be updated. We call this style of effect purely relational or pointfree.
An alternative approach to the specification of effects is to rely on what we call a pointwise update. In this style, rather than specifying how shared
evolves all at once, we make a distinction between the change for input file f
specifically, and the frame condition for files other than f
. This would result in the following alternative specification of share
.
pred share [f : File, t : Token] {
f in uploaded - trashed // guard
historically t not in File.shared // guard
f.shared' = f.shared + t // effect on f.shared
all g : File - f | g.shared' = g.shared // no effect on other shared files
uploaded' = uploaded // no effect on uploaded
trashed' = trashed // no effect on trashed
}
The same style can be used for action predicates delete
and download
. Notice that the latter updates relation shared
if token t
is in its range. Nonetheless, the pointwise style can be used even if the join is performed on the right column of the relation.
pred delete [f : File] {
f in uploaded - trashed // guard
trashed' = trashed + f // effect on trashed
no f.shared' // effect on f.shared
all g : File - f | g.shared' = g.shared // no effect on other shared files
uploaded' = uploaded // no effect on uploaded
}
pred download [t : Token] {
some shared.t // guard
no shared'.t // effect on shared.t
all u : Token - t | shared'.u = shared.u // effect on other shared tokens
uploaded' = uploaded // no effect on uploaded
trashed' = trashed // no effect on trashed
}
Both styles are equivalent, so which one should you favor? Some people prefer the pointwise style because the modification of a field for a specific variable is arguably more salient. On the other hand, the relational style is shorter. Some people like this terseness because they can spot the effect of an action on a field in a single stroke. Ultimately, there are good arguments for both styles, so this is mainly a matter of personal taste!