如何在Crystal中检查函数内是否给定了块参数?

4
假设一个函数定义如下:
def composition(text : String, k : Int32) : Array(String)
  kmers = Array(String).new
  (0 .. text.size - k).each do |i|
    kmers << text[i, k]
    yield text[i, k]
  end
  return kmers
end

如何检查函数中是否给定了块参数? 如果给定了块参数,将会产生kmers。如果没有给定,则kmers将作为字符串数组返回。
2个回答

10

这样的检查是不可能的,因为接受一个块(使用 yield 任何地方)的方法已经有一个需要它的签名。但这也意味着你不需要检查。如果你想要让它可选,只需制作2个像这样的方法:

# if you want to be explicit (makes no difference, this method requires a block):
# def composition(text : String, k : Int32, &block)
def composition(text : String, k : Int32)
  (0 .. text.size - k).each do |i|
    yield text[i, k]
  end
end

# and the non block option
def composition(text : String, k : Int32) : Array(String)
  kmers = [] of String
  composition(text, k) do |s|
    kmers << s
  end
  return kmers
end

3
处理了原帖作者的使用情况,但仍有一个问题,即是否可以确定块是否被传递。可以吗?我认为不行,因为在没有块的情况下调用期望块的函数会导致编译时错误;因此,甚至无法在运行时捕获异常。 - Keith Bennett

2

在您具体的情况下,我建议使用Oleh的答案。但是,这里有一个更通用的解决方案,它可以让您确定是否传递了一个块:

def composition(text, k, &block : String ->)
  composition(text, k, block)
end

def composition(text, k, block : (String ->)? = nil)
  kmers = [] of String
  (0 .. text.size - k).each do |i|
    s = text[i, k]
    if block
      block.call s
    else
      kmers << s
    end
  end
  kmers
end

(有关Proc语法的更多信息,请参见https://crystal-lang.org/reference/syntax_and_semantics/type_grammar.html#proc

以下是另一个可工作的示例:https://forum.crystal-lang.org/t/what-is-the-equivalent-of-ruby-block-given/5059/3?u=zw963 - zw963

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