Gamal Tawaf
Gamal Tawaf

Reputation: 125

Eiffel Iterable implementation on MAP?

I have a class called MAP :

 class MAP [KEY,VAL]
       inherit ITERABLE [KEY]

I implemented the new cursor inside the map cursor which returns and

MAP_ITERATOR_CURSOR [KEY]

and passes that iterable cursor an array of KEYS to iterate through

I implemented the MAP_ITERATOR_CURSOR [KEY] class

 class MAP_ITERATOR_CURSOR [KEY]
       inherit ITERATION_CURSOR [KEY]

for this class I implemented the feature item: VAL but because the class was defined with KEY it won't recognize VAL how do I get MAP_ITERATOR_CURSOR [KEY] item feature to return the VAL associated with the key that we are on at the moment ?

Knowing that MAP has a function called item which take key and returns VAL associated with that key

item (k: KEY): VAL 

Upvotes: 0

Views: 545

Answers (2)

Alexander Kogtenkov
Alexander Kogtenkov

Reputation: 5810

As soon as MAP [KEY, VAL] inherits ITERABLE [KEY], the generic parameter of ITERATION_CURSOR is bound to KEY. However {ITERATION_CURSOR}.item is just a normal feature, that is subject to redeclaration, renaming, etc. Therefore several approaches can fit your need:

  1. Declare MAP_ITERATOR_CURSOR to have two formal generics and declare {MAP}.new_cursor as follows:

    class MAP [KEY, VAL] inherit ITERABLE [KEY] feature
        new_cursor: MAP_ITERATOR_CURSOR [KEY, VAL]
            do
                create Result.make (Current)
            end
    end
    
    class MAP_ITERATOR_CURSOR [KEY, VAL] inherit ITERATION_CURSOR [KEY]
    create make
    feature
        make (t: like target)
            do
                target := t
            end
        target: MAP [KEY, VAL]
        item: KEY ...
        value: VAL
            do
                Result := target.item (item)
            end
    end
    

    Then the client code can look as

    across map as c loop
        -- Use `c.item` of type KEY.
        -- Use `c.value` of type VAL.
    end
    
  2. If it is required that {MAP_ITERATOR_CURSOR}.item is of type VAL, the first way is to use exactly the same code as above but rename feature item that comes from ITERABLE:

    class MAP_ITERATOR_CURSOR [KEY, VAL] inherit
        ITERATION_CURSOR [KEY] rename item as key end
    ...
        key: KEY ...
        item: VAL
            do
                Result := target.item (key)
            end
    end
    

    Then the client code can look as

    across map as c loop
        -- Use `c.item` of type VAL.
        -- Use `c.key` of type KEY.
    end
    
  3. The iteration can be performed over items of type VAL from the very beginning. In that case the actual generic of ITERABLE should be VAL:

    class MAP [KEY, VAL] inherit ITERABLE [VAL] feature
        new_cursor: MAP_ITERATOR_CURSOR [KEY, VAL]
            do
                create Result.make (Current)
            end
    end
    
    class MAP_ITERATOR_CURSOR [KEY, VAL] inherit ITERATION_CURSOR [VAL]
    create make
    feature
        make (t: like target)
            do
                target := t
            end
        target: MAP [KEY, VAL]
        item: VAL
            do
                Result := target.item (key)
            end
        key: KEY
                -- This feature can be not exported, or even not present
                -- as soon as `item` can be implemented.
    end
    

    The client code is similar to case 2, but key may be unavailable:

    across map as c loop
        -- Use `c.item` of type VAL.
    end
    
  4. In 3 the formal generic KEY in MAP_ITERATION_CURSOR is kept for convenience. It can be removed provided that there is some way to access items of MAP, but this may raise some other issues related to access to MAP, conformance and CAT-calls. Therefore though it's potentially feasible, I would not go for it.

Upvotes: 3

Jocelyn
Jocelyn

Reputation: 703

Why not using TABLE_ITERABLE [G,K] ?

cf https://svn.eiffel.com/eiffelstudio/trunk/Src/library/base/elks/kernel/table_iterable.e

Upvotes: 0

Related Questions