Obj.as(obj.class) ^ Error: expecting token 'CONST', not 'block'

Hi! I have a problem with the type handling… :frowning:

@blocks : Array(T) # Array(Gusano::Block(Int32, Nil) | Gusano::Block(String, Nil))

def start(params)
  block = @blocks.find { |el| el.name == @actual_block }

  if block.nil?
    # TODO
    block.as(block.class).run params # <- Error

I need to cast block to its real type. @blocks is an array and the objects inside are instances of a generic class so I get this error:

Error: no overload matches 'Proc(Tuple(String), Nil)#call' with type Tuple(Int32)

Overloads are:
 - Proc(T, R)#call(*args : *T)

Could anybody help me? Thank you! :confused:

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.

Hi! Thank you for your help… I have uploaded the simplified version of the code to the official online compiler:


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 }
  def run(*params)
    @exec_fn.call params
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
block1 = Block(Int32, String).new :init { |a| a.to_s }
block2 = Block(String, Int32).new :end { |str| str.to_i }
engine = Engine.new(
engine.start 123


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).

I think that might be the problem.

There’s no way to it that way.

You sure can get interesting error messages after playing for a while

Error: no overload matches 'Block(Tuple(Int32))#run' with type Tuple(Int32)

Overloads are:
 - Block(T)#run(params : T)


1 Like


I find that error a bit confusing. I have seen the modifications you made and it.

And after playing for a while:

block.as(Block(typeof(params))).run params 
# Error: can't cast (Block(Int32) | Block(String)) to Block(Tuple(Int32))

I think I’ll pause this. I’ve been at this for several hours and I still don’t fully understand the type system :( Thank you!

What I mean is, the way you are coding it will never work, but the program you want to build is definitely possible.

Could you explain what are you trying to build?

1 Like

My idea is to have blocks that execute a function (proc) and that can be connected to each other…

Block A, B


I think it could be useful for visual programming, some rpc tool or even to create a Workflow Automation tool.

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

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.

1 Like