When parentheses matter

by Alexander Kogtenkov (modified: 2017 Mar 02)

Recently I've run into an issue that can be summarized by the following code snippet:

class TEST create make feature make local s1, s2: STRING do s1 := {TEST}.name s2 := ({TEST}).name end name: STRING = "Hi there!" end

Question 1. Will s1 and s2 have the same value? (Before reading the answer you may want to answer the question yourself.)

Test. Let's add two lines of code print (s1 + "%N") print (s2 + "%N")
and look at the output: Hi there! !TEST
Why so?

Answer. The first syntax is used to access constant attributes, so the string is the value of the attribute name of class TEST. In the second case there is no immediate qualified call on {TEST} and it is considered as a reference to the type object for type TEST and has a type TYPE [TEST]. Accidentally class TYPE declares a feature name that returns a run-time name of the associated type. (The exclamation mark in front of it indicates that the type is attached.)

Are there other cases when enclosing types in braces affects code semantics? Yes: there are open arguments in agent declarations!

Question 2. What would be result of the code above if assignment to s1 and s2 are changed into the following? s1 := (agent {ANY}.generating_type).item (Current) s2 := (agent ({ANY}).generating_type).item (Current)

Test. The same print statements give us TEST TYPE [!ANY]

Answer. The first syntactical construct corresponds to the declaration of an agent with an open target and produces an agent object of type FUNCTION [TUPLE [ANY], TYPE [ANY]]. The actual target is then passed as an argument to the feature item. In the second case the target is closed and the agent has type FUNCTION [TUPLE, TYPE [TYPE [ANY]]]. This explains the output we get.

Final question for curious developers: what part in the second example is redundant and can be removed without affecting execution?