Capturing blocks with multiple allowed types/signatures

Viewed 95

Is it possible to capture a block inside a method that has multiple allowed signatures?

alias IoBlockFormatter = Severity, Time, String, String, IO -> Nil
alias StringBlockFormatter = Severity, Time, String, String -> String

class Formatter
  def initialize(@io : IO, &@block : IoBlockFormatter | StringBlockFormatter)
  end
end

In this example, I'm defining two different function types, and I want to allow the block that my Formatter class can accept to be either type. My first attempt at this tries to use the union of the two types, but the compiler complains about expecting a Function type, not a union of two Proc types.

expected block type to be a function type, not (Proc(Severity, Time, String, String, IO, Nil) | Proc(Severity, Time, String, String, String))

  def initialize(@io : IO, &@block : IoBlockFormatter | StringBlockFormatter)
1 Answers

You cannot have one method take multiple block types, as the block is typed from the method signature, not the other way around. Once the correct method is found, the types of the block arguments are deduced from yield with non-captured blocks, and from the type of &block in captured arguments. You also cannot have two overloads with the same arguments and a block, even if the block is used differently for similar reasons.

Related