Re: OCL challenge



Date view Thread view Subject view Author view

Tony Simons (a.simons@dcs.shef.ac.uk)
Thu, 21 Dec 2000 10:45:16 +0000 (GMT)


Hi Jos, Thanks for the reply. I think I mostly talked to Anneke at TOOLS Eur. 99 about this, so you (personally) may not have heard these arguments. I agree that -> disambiguates some things that are otherwise confused, but my point is that it is the *wrong kind of fix*. Preliminaries: let p be an object with two attributes, q : Set(Element) and r : Element. Let Set have a method size : int and Element have a method id : int. (Neither method has any additional arguments). The main point is the following: the syntactic fix introduced by using p.q->size instead of p.q.size is addressing a consequential ambiguity (how to distinguish set methods from element methods), resulting from merging the distinction between p.r meaning "access the attribute r of p" and p.q meaning "map over every element of the set q reached from p". The fix addresses the wrong problem; the problem that it addresses is an artificial one introduced by getting something else wrong before. A more appropriate fix would address that fault at source, and so not introduce any further consequential ambiguity. I think you will agree that it is always good to have a direct correspondence between notations and semantics. But here, we have the opposite: p.q and p.r are syntactically identical, but they have a hidden different semantics: one is a simple access "the Element r stored in p", the other is a mapping operation "for all Elements in the Set q stored in p". The consequential effects are also problematic: in p.q->size and p.r.id, the subexpressions q->size and r.id are syntactically different, but they have the same semantics - invoking a method of the target variable (as a whole). This kind of occurrence should always raise alarm-bells in the minds of notation designers! The notational problem is that the semantic distinction between . meaning "simple access" and . meaning "mapping operation" is only signalled later by subsequent operators in the access path. In: p.q.id we must understand that p.q maps over every element of the set, such that (p.q).id is a meaningful operation on Elements (under the normal rules of left-to-right evaluation); compare this with: p.q->size in which we have to wait for -> before we can understand that the preceding p.q refers to the set itself. My argument is that the visual cues to the semantic differences occur in the wrong place. The reader has to backtrack when reading expressions, and it becomes impossible to interpret subexpressions, like the (p.q) above, when these are lifted out of their context, compare: (p.q).id (p.q)->size and note how the interpretation of the bracketed expressions has to be different, under the normal left-to-right evaluation semantics. Now, let's change some things. If we assert that p.q always returns a SINGLE OBJECT and never maps implicitly over the elements of sets, then we defer the task of signalling mapping operations, or simple method invocations. In what follows, I redefine some OCL operators: Let the "dot" . be the selector which always returns the object stored in an attribute as a whole, such that the return types of the following expressions are: p.r : Element p.q : Set(Element) in other words, p.q returns the SET, and does not EVER implicitly map over every element of the set. This means that the following expressions are meaningful and consistent: p.q.size : int // return the size of a set p.r.id : int // return the id of an element because we can extract the subexpressions: q.size and r.id and these can be interpreted consistently as the same kind of semantic operation (an invocation on a target object as a whole). The following is quite different from OCL, so heads up everyone. Let the "arrow" -> be the selector which maps a method over every Element of the set-valued expression at the source of the arrow, such that the return types of the following expressions are: p.q->id : Set(int) p.q.size : int in other words, the novel visual distinction q->id signals a mapped method, in contrast with q.size which signals a normal method. This is desirable, because the "dot" . notation is now used consistently everywhere to invoke a method on the preceding target variable, which is always understood to be a single object taken as a whole. The two checks we have been applying above also make sense here. In: (p.q)->id (p.q).size the subexpression (p.q) always returns a Set(Element) in both cases (no implicit mapping over elements). Likewise, extracting the subexpressions: q->id and q.size shows directly, in the notation, where a semantic distinction is intended. Furthermore, the "marked" version, which signals something different over what you normally expect, is the arrow, meaning "mapped method", contrasting with dot, meaning "normal method". This usage contrasts with the current OCL in which the dot and arrow notations are deployed in precisely the REVERSED senses, when applied to set-valued objects ONLY, but the dot IS deployed in this normal sense when applied to simple-valued objects. There are two aspects of this that are disturbing: one is the inconsistent use of dot over different types of target object; the second is the reversal of syntactic cues and semantic meanings in the deployment of the arrow/dot notation for set-valued objects. Best wishes, --Tony ========================================================================== Dr Anthony J H Simons a.simons@dcs.shef.ac.uk Lecturer in Computer Science http://www.dcs.shef.ac.uk/~ajhs Director of Teaching Department of Computer Science tel: (+44) 114 22 21838 University of Sheffield dept: (+44) 114 22 21800 Regent Court, 211 Portobello Street fax: (+44) 114 22 21810 SHEFFIELD, S1 4DP univ: (+44) 114 22 22000 United Kingdom ==========================================================================


Date view Thread view Subject view Author view