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?