Reputation: 5083
I'm trying to create some terminal logging colors to be able to see clearer my errors. Doing that it seems to me obvious that I'd have to create constants like followings. As I don't want to create an instance each time I call my constant, it makes sense for me to do something like that, but the compiler doesn't seem to have the same conception as me...
A once function has generic or anchored result
what is an anchored
result?
As the compiler has always the last word and me the forelast, why am I wrong and is he right??
class
TERMINAL_COLOR
create
make
feature -- Initialization
make (a_fg: like foreground; a_bg: like background)
do
foregound := a_fg
background := a_bg
end
feature -- Status report
foreground: INTEGER
background: INTEGER
feature -- Colors
Black: like Current
once -- compiler doesn't agree with me
create Result.make (30, 40)
ensure
instance_free: class
end
end
Upvotes: 0
Views: 105
Reputation: 703
An anchor type is when you use the "like feature" (note you can also use "like {FOO}.bar" ).
Also, don't forget the Once is "once per class" (not by type). That's why the result type for a once function could not be using any formal generic. For instance
class FOO [G]
feature
bar: STRING
once
Result := generating_type
end
end
(create {FOO [INTEGER]}).bar
will return the same object as (create {FOO [STRING]}).bar
.
So, now if bar
would return G
in class FOO, it would cause trouble as there is no way to return a value that conforms to any formal (INTEGER, STRING, ...).
That's why generic are forbidden for once result type.
The same logic applies to anchor type such like feature_name
, as feature_name
could be redefined in descendant with other types.
Upvotes: 2
Reputation: 5790
Indeed, once functions are not allowed to return a value of an anchored type or of a formal generic type. The reason lies in the semantics of a once function: its body is executed only one time (I'm leaving out more complex cases with recursion) regardless of the current object type.
In your example, it would be possible to have a descendant of the class TERMINAL_COLOR
, say, TOUCH_PAD_COLOR
(whatever it means):
class
TOUCH_PAD_COLOR
inherit
TERMINAL_COLOR
create
make
feature
touch_color: like Current
-- Color for visual indication of user interaction.
...
end
Let's look what happens in the following code:
t: TERMINAL_COLOR
p: TOUCH_PAD_COLOR
...
t := {TERMINAL_COLOR}.black
p := {TOUCH_PAD_COLOR}.black
Because black
returns like Current
, both assignments are valid: the type of black
is TERMINAL_COLOR
in the first call and TOUCH_PAD_COLOR
- in the second. However, the body of the feature black
is executed only once, namely, in the first call. And the type of the computed object is TERMINAL_COLOR
. In the second assignment, previously computed object is returned without executing the body of the function black
. The type of the object is still the same: TERMINAL_COLOR
. But now this object is attached to the entity p
of type TOUCH_PAD_COLOR
. Making a call on p
, e.g. p.touch_color
would result in a crash because there is no method touch_color
in the class TERMINAL_COLOR
.
As to terminology, anchored types denote types declared in terms of some other entities. For example, like Current
refers to the type of the current class.
Disclaimer. There are different kinds of once features, the scenario above deals with the most common case.
Upvotes: 3