Search code examples
eiffel

Is there a way to specify various types for a parameter


Is there a way to restrict the conformance of a type to be a collection of types?

Let me explain by example:

give_foo (garbage: ANY): STRING
    do
        if attached {STRING} garbage as l_s then
            Result := l_s
        elseif attached {INTEGER} garbage as l_int then
            Result := l_int.out
        elseif attached {JSON_OBJECT} garbage as l_int then
            Result := l_int.representation
        elseif attached {RABBIT} garbage as l_animal then
            Result := l_animal.name + l_animal.color
        else
            Result := ""
            check
                unchecked_type_that_compiler_should_be_able_to_check_for_me: False
            end
        end
    end

Couldn't I do something like (like a convert function could do)

give_foo (garbage: {STRING, INTEGER, JSON_OBJECT, RABBIT}): STRING
    do
        if attached {STRING} garbage as l_s then
            Result := l_s
        elseif attached {INTEGER} garbage as l_int then
            Result := l_int.out
        elseif attached {JSON_OBJECT} garbage as l_int then
            Result := l_int.representation
        elseif attached {RABBIT} garbage as l_animal then
            Result := l_animal.name + l_animal.color
        else
            Result := ""
            check
                unchecked_type_that_compiler_should_be_able_to_check_for_me: False
            end
        end
    end

or something like

not_garbage_hash_table: HASH_TABLE[{INTEGER, STRING, ANIMAL}, STRING]

Solution

  • Conformance to a collection of types is not supported for several reasons:

    • Calling a feature on an expression of such a type becomes ambiguous because the same name could refer to completely unrelated features.
    • In one case we need a sum (disjoint union) of types, in the second - plain union, in the third - an intersection, etc. And then, there could be combinations. One would need an algebra built on top of a type system that becomes too complicated.
    • If the requirement is to check that an argument is one of expected types, the following precondition can be used:

      across {ARRAY [TYPE [detachable ANY]]}
              <<{detachable STRING}, {INTEGER}, {detachable JSON_OBJECT}>> as t
      some argument.generating_type.conforms_to (t.item) end
      
    • A common practice to process an expression of a potentially unknown type is a visitor pattern that deals with known cases and falls back to a default for unknown ones.