如何将方法传递给 Crystal 中的块

How to pass method to block in Crystal

如何将 plus 传递给 calculate 方法?

def calculate(&block : (Float64, Float64) -> Float64)
  block.call(1.1, 2.2)
end

def plus(a, b)
  a + b
end

calculate{|a, b| plus a, b}

这行不通

calculate ->plus
calculate &plus

P.S.

另一个问题,如何让它适用于所有数字?不只是 Float64。此代码不会编译并抱怨要求比 Number

更具体的类型
def calculate(&block : (Number, Number) -> Number)
  block.call(1, 2)
end

理想情况下,最好将其推广,以便 typeof(block.call(1, 2)) => Int32typeof(block.call(1.1, 2.2)) => Float64

How to pass plus into calculate method?

您正在寻找

calculate(&->plus(Float64, Float64))

其中->plus(Float64, Float64)returns一个Proc。请注意,您 指定参数的类型 - 请参阅参考手册中的 From methods 部分。

how to make it to work for all numbers?

我会研究 forall - 请参阅参考手册中有关 Free variables 的部分。

通用解决方案可以使用自由变量,但有一个问题,因为不能从块参数派生自由变量:

def calculate(&block : (T, T) -> T) forall T # Error: undefined constant T

这是因为块参数不能被重载,因为它们可以简单地被捕获块而没有类型限制。

有两个选项可以使这项工作生效:

  1. 您可以将 T 的类型作为参数显式传递。这有点冗长,但适用于捕获的块参数。
def plus(a, b)
  a + b
end

def calculate(t : T.class, &block : (T, T) -> T) forall T
  block.call(1.1, 2.2)
end

calculate(Float64, &->plus(Float64, Float64))
  1. 您可以将捕获的块参数更改为接收 Proc:
  2. 的普通参数
def plus(a, b)
  a + b
end

def calculate(block : (T, T) -> T) forall T
  block.call(1.1, 2.2)
end

calculate(->plus(Float64, Float64))