【问题标题】:How to get the name of the arguments passed into a block?如何获取传递到块中的参数名称?
【发布时间】:2018-03-14 21:22:49
【问题描述】:

在 Ruby 中,您可以这样做:

prc = lambda{|x, y=42, *other|}
prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :other]]

特别是,我对能够获取上述示例中的xy 参数的名称很感兴趣。

在Crystal中,我有以下情况:

def my_method(&block)
  # I would like the name of the arguments of the block here
end

如何在 Crystal 中做到这一点?

【问题讨论】:

    标签: crystal-lang


    【解决方案1】:

    虽然这在 Ruby 中听起来很奇怪,但在 Crystal 中无法做到这一点,因为在您的示例中,该块已经没有参数了。另一个问题是这些信息在编译后已经丢失。所以我们需要在编译时访问它。但是您不能在编译时访问运行时方法参数。但是,您可以使用宏访问该块,然后甚至允许该块的任意签名而无需明确给出它们:

    macro foo(&block)
      {{ block.args.first.stringify }}
    end
    
    p foo {|x| 0 } # => "x"
    

    【讨论】:

      【解决方案2】:

      为了扩展 Jonne Haß 的出色答案,Ruby parameters 方法的等效项是这样的:

      macro block_args(&block)
        {{ block.args.map &.symbolize }}
      end
      p block_args {|x, y, *other| } # => [:x, :y, :other]
      

      请注意,Crystal 中始终需要块参数,并且不能有默认值。

      【讨论】:

      • 如果块没有参数(即block_args {}),这将给出语法错误
      • 是的,它非常粗略,仅作为一个基本示例。例如,它还省略了 other 是一个 splat(尽管 Ruby 似乎也没有报告这一点)。
      • 哦不,在Ruby中它被归类为:rest
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2019-04-02
      • 2019-11-20
      相关资源
      最近更新 更多