This week we begin taking a look at Scrall action language examples.

Today, we’re just going to stick our hands in the cookie jar and grab objects directly. In next week’s post we will hop lithely across associations to find the objects we need.

Since we aren’t using any associations today, we will use single class examples only, like this one:

I will be using miUML in my examples which is quite similar to any sm (Shlaer-Mellor) executable UML, such as xtUML. See my previous post for more about sm UMLs. As we go along, I will be explaining any conventions unique to Shlaer-Mellor for those not familiar with this branch of executable UML.

The {I} notation is a standard miUML attribute tag which expresses the identity or uniqueness constraint. An identifier, in Shlaer-Mellor, is a set of one or more attributes such that a set of corresponding values will yield either one or zero objects in a populated model. In our example, Tail number is a single attribute identifier defined on the Aircraft class.

Task 1: Grab that object

We often receive an identifier value (or set of values) from some source and then try to grab a reference to the associated object. And this is exactly what we are doing here with Scrall:

my aircraft .= Aircraft( Tail number: in.aircraft id )

Starting on the right hand side of the assignment, we see a reference to the Aircraft class with a selection clause designated by the attached parentheses. The single identifier attribute Tail number is matched against the aircraft id parameter which is an input to this activity as indicated by the in keyword prefix.

And, oh yes he did, space character delimiters are valid inside variable and model element names.

You’re welcome.1

Convenience feature: Implicit matching

Read the : symbol, in the context of selection, to mean ‘match using this criteria’. In the simplest and most common case, that criteria is ‘= x’ and since it is so common, it is the default matching criteria when no other criteria such as !=, > >=, etc is specified. Though, if you like, you could write Aircraft( Tail number: = in.aircraft id ).

This is a minor thing, but the accumulation of many small conveniences will lead us to a language that is easier to read and write.

Implicitly defining an object variable

In the example above, we know that the Aircraft(…) selection must return zero or one object reference every time. This is because an identifier value is being matched. Not so coincidentally, the .= assignment operator requires an expression on the right hand side that returns zero or one object reference. Think of the . as meaning ‘a single object or no object’.

The action language analyzer has access to the class model and will check to see if you are performing a selection matching an identifier value. If not, a .= assignment will trigger a static error.

The special assignment operator is also saying: “It really is my intention to grab the empty set or a single object2”. We want the modeler’s intentions to be explicit so that we can spot mistakes more quickly and force the modeler to think things through.

On the left hand side, the .= assignment operator requires a new or existing single object variable.

In this case, the .= assignment operator establishes the type of the newly defined variable my aircraft. (‘my’ is not a keyword, it is just part of the variable name3). The variable has been implicitly typed as a single Aircraft object. You may not later try to assign a Pilot object without getting a static error.

General rules about Scrall variables

  1. All variables are local to the current activity.
  2. Within an activity, all variables are at the same scope.
  3. Every variable has a type which is defined either implicitly through assignment or with an explicit definition. For object and relation4 variables, the assignment operator will determine the type. For data variables, the right hand type determines the type on the left side.
  4. Once defined, a variable may not be redefined. So the type of a variable never changes.

These rules may seem a bit restrictive compared to those for programming language variables. But we are taking advantage of the fact that local activity scope is tightly focused and we’ve got a CLASS MODEL so the notion of local/global becomes rather quaint.

Unique selection with multiple attributes

Here’s a class with a more interesting identifier:

Note that there are two {I} tags in this class which means that you need both an ID value (such as 090) and an Airport value (such as SFO) to tell one Runway object apart from another. The R8 tag, in miUML, indicates a referential attribute on an association named R8. The referential attribute tag expresses another constraint. The constraint is 1) that the Runway.Airport referential attribute corresponds to the Airport.ID identifier attribute5 and 2) that, for any Runway object, its Airport attribute value, if it has one6, must correspond to the ID value of some instance of Airport.

So to grab a particular instance of Runway using supplied parameters for Runway ID and Airport values, you would do this in Scrall:

assigned runway .= Runway( ID: in.ID, Airport: in.Airport )

Convenience feature: Parameter doubling unnecessary

In the above example the input parameter names just happen to match the attribute names. It is not at all uncommon to see the variable names for supplied values match attribute or formal parameter names. This parameter doubling pattern is common to all programming languages and I’ve always found it annoying.

So, as the mighty GOD of Scrall <thunder clap>, I hereby declare that when attribute or signature parameter names match, you need specify only the supplied value name without fear of smite from a nit-picky parser. For example…

assigned runway .= Runway( in.ID, in.Airport )

… will work just fine. The language analyzer will see that you haven’t specified the attributes and assume that the variable names must match. If they don’t, you will get a static error. And order does not matter so this also works:

assigned runway .= Runway( in.Airport, in.ID )

Now, there is one flaw in this plan and feel free to point it out to get bonus points! That said, I’ve already got a solution ready that will

  • blow
  • your
  • mind

I’m going to save it for a future post though.

Task 2: Get me those objects

So much for single object variables. If you want multiple objects, you need to define a multi object variable. Let’s say you want to select all Aircraft above a certain altitude. You could do this in Scrall:

high flying aircraft ..= Aircraft( Altitude: > high alt )

The many object assignment operator ..= implicitly defines high flying aircraft as a multi object variable. After the assignment, this variable may refer to zero, one or many objects. To get all aircraft just do this:

allAircraft ..= Aircraft()

Actually, you don’t need the parentheses, so this is also fine:

allAircraft ..= Aircraft

By the way, all is a keyword to be introduced later so you shouldn’t name your variable all aircraft. Too bad there isn’t such a thing as a ‘hard space’ for the parser to detect. Then keywords wouldn’t be a problem!

Task 3: Get me some object

Maybe you only want one object, say, the fastest aircraft. Since there could be multiple aircraft flying at the same speed, you need to grab an arbitrary instance (for lack of any other criteria). Use the .=. arbitrary object assignment operator.

fastest plane .=. Aircraft( ^+Airspeed )

Two things are going on here. The unary max ^+ operator selects out the Aircraft instances with the highest Airspeed attribute values. The .=. operator assigns one of the available instances from the right hand side, or the empty set if there are none. You can think of the right dot feeding one object or no object into the assignment and flowing out the other side as a single object assignment.

The above example will fail with an error if you try to use the .= assignment operator since the right hand expression can yield more than one object.

When multiple max,min operators are applied, the order within the selection clause matters:

lowest fastest aircraft .=. Aircraft( ^-Altitude, ^+Airspeed )
fastest lowest aircraft .=. Aircraft( ^+Airspeed, ^-Altitude )

The first assignment selects the highest aircraft first and then chooses the fastest among them. The second chooses the fastest aircraft first and then the lowest.

high fast aircraft ..= Aircraft( Altitude > high alt and Airspeed > high speed )

Standard logic operators like and, or, not and comparison operators =, >, <, >=, <=, != may be used in a selection assuming they have been defined on the types being compared.

miUML supports and requires the definition of operations on types.

Other details

Names are not case sensitive.

Lines end on newline.

Backslash to connect long lines.

You don’t need backslashes if you split a line within parenthesis, brackets or braces.

Comments // and /* */ just like in C, C++

NEXT UP, relationship/association hopping. See you next week.

  1. This feature does challenge the parser. But we prefer to put the burden on the tools rather than the model developer.
  2. In the context of Scrall I will use the term object instead of ‘object reference’ unless there is some reason to make a distinction.
  3. The modeler must be careful not to use keywords in symbol names. Consequently, we strive to define as few keywords as possible and make them obvious. Is it too much to ask a developer to avoid using ‘if’ in a variable name?
  4. Described in a future post.
  5. The name mapping Runway.Airport -> Airport.ID is not shown on an sm UML class diagram, but is recorded in the Runway.Airport attribute description as well as the miUML metamodel. (The expert trick is to be systematic in your naming of referential attributes).
  6. I will delve into the systematic handling and significance of ‘empty’ referential attributes in a later blog entry. For now, be happy that there are no zeros in the 1 to 1..* association to Airport 😉
Want to build better software faster?

Want to build better software faster?

Read about the latest trends on software modeling and low-code development

You have Successfully Subscribed!

Pin It on Pinterest

Share This