Hi pals,
I have code like this:
abstract class Expression
end
class IntLiteral < Expression
end
class BoolLiteral < Expression
end
hash = {} of String => -> Expression?
hash["a"] = ->my_method
def my_method : Expression?
return IntLiteral.new
end
It fails with this error.
Error: no overload matches 'Hash(String, Proc((Expression | Nil)))#[]=' with types String, Proc(IntLiteral)
I was expecting that:
- Take the method signature
: Expression?
as type or
-
IntLiteral
is an Expression?
What I’m getting wrong? How can I solve this?
Explicitly casting to Expression?
in the return do the trick but seems clunky
Hello. I’m not really sure what’s going on here, but I think it should be simply String => Expression?
, and accordingly, hash["a"] = my_method
. Or, unless there are actually going to be Nil
s in the hash, just String => Expression
.
Hopefully someone else will join in to explain the details, I didn’t even expect ->
to work on anything other than blocks and methods.
facepalm. misunderstood syntax and code intent. quietly crawling back under a rock.
The type is String => -> Expression?
meaning a String
as key and a Proc that doesn’t have parameters and returns Expression?
as value
The solution for this is simple, there is no solution as Covariance and Contravariance aren’t fully supported as per documentation
So I ended forcing the type
def my_method : Expression?
return IntLiteral.new.as(Expression?)
end
To make it prettier I put the cast inside a macro so it looks cleaner.
macro rexp?(r)
return {{r}}.as(Expression?)
end
def my_method
rexp? IntLiteral.new
end
It works ok for me now
Right now a return type is a restriction: the compiler checks that the returned value matches the return type, but the actual returned type might be a subtype.
We should probably change this.
I suggest you send a feature request to the Github repository.