如何在Crystal中将方法传递给代码块

3
如何将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

2个回答

6
如何将加号传递到计算方法中?
你需要使用以下代码: ``` calculate(+) ```
这将把加号(+)作为参数传递给计算方法。
calculate(&->plus(Float64, Float64))
->plus(Float64, Float64) 返回一个Proc。请注意,您必须指定参数的类型-请参阅参考手册中的节"From methods"

如何使其适用于所有数字?

我建议查看参考手册中的"Free variables"章节中的forall

2

一个通用解决方案可以使用自由变量,但有个问题是自由变量无法从块参数中派生:

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

这是因为块参数不能被重载,因为它们只是没有类型限制的捕获块。
有两个选项可以使其工作:
1. 您可以显式地将T的类型作为参数传递。这样会有点冗长,但可以与捕获的块参数一起使用。 2. 或者您可以使用单个方法来处理所有类型,并将其称为泛型方法。
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的普通参数:
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))

谢谢。实际上,我想要一个普通的参数,我添加了Proc,因为我以为这是应该这样的方式 :)。 - Alex Craft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接