The code is a bit too much of fragment to really tell what’s going on and what you really want.
The error is a conceptual one. block.class is a runtime value, however .as operates (at least partly) in compile time. It needs to generate the right native code for the call with the right signature after all.
I’m sure this code produces a syntax error. block.as(block.class) is invalid. The argument to as must be a constant.
There should be no way this could possible parse. Just parsing the snipped you provided without any context shows that syntax error.
class Block(*T, U)
@exec_fn : Proc(T, Void)
getter name
def initialize(@name : Symbol, &fn : *T -> U)
@exec_fn = ->(params : T) { fn.call *params }
end
def run(*params)
@exec_fn.call params
end
end
class Engine(T)
@actual_block : Symbol
@blocks : Array(T)
def initialize(@blocks : Array(T), @actual_block : Symbol); end
def start(params)
block = @blocks.find { |el| el.name == @actual_block }
if !block.nil?
block.run params
end
end
end
block1 = Block(Int32, String).new :init { |a| a.to_s }
block2 = Block(String, Int32).new :end { |str| str.to_i }
engine = Engine.new(
[
block1,
block2,
],
:init
)
engine.start 123
Output:
Showing last frame. Use --error-trace for full trace.
error in line 10
Error: no overload matches 'Proc(Tuple(String), Int32)#call' with type Tuple(Int32)
Overloads are:
- Proc(T, R)#call(*args : *T)
The @blocks array is: Array(Gusano::Block(Int32, Nil) | Gusano::Block(String, Nil)). So, the block type on the #start function is Gusano::Block(Int32, Nil) | Gusano::Block(String, Nil).
This might be possible in the future if there’s a way to do if x.is_a?(Proc(Int32, _)), but right now you can’t use underscore in is_a?. Then you could do something like:
def start(params : *T) forall T
block = @blocks.find { |el| el.name == @actual_block }
if block.is_a?(Proc(*T, _))
block.run params
end
end
I made underscore kind of work during the weekend by hacking something, but then something else breaks and then I ran out of time. I doubt this will be fixed before 1.0.
What you want to do is definitely possible if you model it in a different way. But exactly like you are doing it here will never work due to language limitations.