I am trying to make an iterator for for a linked_list in Eiffel.
I am getting this error: Variable is not set properly.
Class: ITERATOR_ON_COLLECTION [E]
Feature: make
Attribute(s): {ITERATOR}.target
Line: 30
I know it's because of void safety but I don't know how to fix it. (I set void safety to True and changed the precompiled library to safe version and clean_compile it.)
the following is the class:
class
ITERATOR_ON_COLLECTION [E]
inherit
ITERATOR [E]
create
make
feature {NONE} -- Attributes
collection: LINKED_LIST[E]
item_index: INTEGER
feature -- initialization
make(c: LINKED_LIST [E])
require
--c /= void
do
-- create {COLLECTION} collection.make
-- create collection.make -- it doesnt work with/without this line
collection := c
item_index := 1
end
start
do
item_index := 1
end
item: STRING
do
Result := "hello"
end
next
do
item_index := item_index + 1
end
is_off: BOOLEAN
do
Result := True
end
do_until (action: PROCEDURE [E]; test: FUNCTION [E, BOOLEAN])
-- Apply `action' to every item of `target' up to
-- and including first one satisfying `test'.
-- (Apply to full list if no item satisfies `test').
require else
action_exists: action /= Void
test_exists: test /= Void
do
end
do_while (action: PROCEDURE [E]; test: FUNCTION [E, BOOLEAN])
-- Apply `action' to every item of `target' up to
-- and including first one not satisfying `test'.
-- (Apply to full list if all items satisfy `test').
require else
action_exists: action /= Void
test_exists: test /= Void
do
end
until_do (action: PROCEDURE [E]; test: FUNCTION [E, BOOLEAN])
-- Apply `action' to every item of `target' up to
-- but excluding first one satisfying `test'.
-- (Apply to full list if no items satisfy `test'.)
require else
action_exists: action /= Void
test_exists: test /= Void
do
end
while_do (action: PROCEDURE [E]; test: FUNCTION [E, BOOLEAN])
-- Apply `action' to every item of `target' up to
-- but excluding first one satisfying not `test'.
-- (Apply to full list if all items satisfy `test'.)
require else
action_exists: action /= Void
test_exists: test /= Void
do
end
there_exists (test: FUNCTION [E, BOOLEAN]): BOOLEAN
-- Is `test' true for at least one item of `target'?
require else
test_exists: test /= Void
do
end
for_all (test: FUNCTION [E, BOOLEAN]): BOOLEAN
-- Is `test' true for all items of `target'?
require else
test_exists: test /= Void
do
end
end
Without looking at the class ITERATOR
it's hard to tell what is the real cause. Here is my guess what happens:
Class ITERATOR
declares an attribute target
of an attached type. The attribute has to be set in your creation procedure. Most probably you need to discard the attribute collection
in your class and use target
instead. Depending on the attribute's type you may need to redefine it in your class or not.
In terms of efforts it's better to start from void-safe versions of classes right from the beginning and when you switch from a non-void-safe settings to void-safe ones, you may need to make sure that the class types are attached by default (look for a configuration option "Are types attached by default?" in projects setting dialog). This option should be set to True (this is not done automatically in EiffelStudio prior to 16.11).
A few comments on other parts of the code:
If an argument type is attached there is no point of checks in the form arg /= Void
.
If a precondition foo
is specified for a feature in a parent class there is no need to repeat it like
require else
foo
It can be safely removed. (You can look at the feature flat (or flat short) form to see that the parent's precondition is still there.)
If comments of redefined features are not changed, they can be replaced with
-- <Precursor>
This way any changes in parent's versions will be automatically reflected in redeclarations (again have a look at the flat form).