Passing an array of Procs to a function

Ok, last question for today (I don’t want to flood ;-) )

I’ve this

walk(@program, ->transform_literal(AST::Node))
walk(@program, ->check_ident_type(AST::Node))

def walk(node : AST::Node, fn)
    fn.call(node)
    node.children.each do |child|
      walk(child, fn)
    end
end

Not very smart because I walk the AST tree twice

So I tried

operations = Array(-> (AST::Node)).new
operations << ->transform_literal(AST::Node)
operations << ->check_ident_type(AST::Node)
walk(@program, operations)

def walk(node : AST::Node, fns : Array(-> (AST::Node)))
end

But I get a compilation error on operations << ->transform_literal(AST::Node)

Error: expected argument #1 to 'Array(Proc(AST::Node))#<<' to be Proc(AST::Node), not Proc(AST::Node, (TypeBase | Nil))

And I don’t understand it

The proc that you’re trying to add has the input type AST::Node and output type TypeBase | Nil.
That doesn’t fit into an array which expects a proc with no input and output type AST::Node. Just adjust the array type accordingly and you should be good.

I don’t get it, the transform_literal proc I’m trying to add is defined as

def transform_literal(node : AST::Node)
end

There’s no TypeBase | Nil as output type

If that is the literal definition, it would be typed as AST::Node → Nil

But my transform_literal function is not intended to return Nils, it’s a return Void function…

Sorry, that’s me but I don’t understand

Does Array(-> (AST::Node)) mean : an Array of Proc expecting an AST:Node parameter type on input and Void type on output ?

Try Array(AST::Node ->).

There’s no useful distinction in Crystal between Void and Nil types. If your proc doesn’t return a value, it’s nil.

def call
end

value = call
pp typeof(value) # Nil

Thanks ! That works

I’ve been fooled by the fact that a Proc is defined as

proc = ->(x : Int32, y : Int32) { x + y }
proc.call(1, 2) # => 3

In which → is followed by the input parameter types
whilst in my case → is the return type

A lot still to learn, obviously ;-)

Good point. That can be a bit confusing.