I'm trying to implement Ruby's function composition operator <<
into Crystal's proc. In Ruby it seems pretty straight forward.
def << block
proc { |*args| self.call( block.to_proc.call(*args) ) }
end
end
I've tried to do something similar.
struct Proc
def <<(&block)
Proc.new { |*args, blk| call(block.call(*args, blk)) }
end
end
I've tried testing it with a simple adder and suber function
def add(x : Int32)
x + 1
end
def sub(x : Int32)
x - 1
end
But, I'm getting this error. Error: wrong number of arguments for 'Proc(Int32, Int32)#<<' (given 1, expected 0)
I've also tried changing the <<
to take in a proc but that also results in expected block type to be a function type, not Proc(*T, R)
I'm kind of new to the language so I'm not too sure what knowledge I'm missing to understand why this is not working.
You get this error because Proc
is underspecified. The Proc
type is a generic type and needs to be instantiated with specific generic arguments that describe the types of its parameters and the return type.
You can see the same behaviour with a minimal example:
Proc.new { 1 } # Error: expected block type to be a function type, not Proc(*T, R)
Granted, the error message is not very telling.
A working example for what you try to achieve could look like this:
struct Proc
def <<(block : Proc(*U, V)) forall U, V
Proc(*T, V).new { |arg| call(block.call(arg)) }
end
end
def add(x : Int32)
x + 1
end
def sub(x : Int32)
x - 1
end
x = ->add(Int32) << ->sub(Int32)
p! x.call(10)