Pipo
Pipo

Reputation: 5083

Eiffel: once function has generic or anchored result. Trying to create constants

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

Answers (2)

Jocelyn
Jocelyn

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

Alexander Kogtenkov
Alexander Kogtenkov

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

Related Questions