ruby – 我可以对传递给方法的块强制执行arity吗?

前端之家收集整理的这篇文章主要介绍了ruby – 我可以对传递给方法的块强制执行arity吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有没有办法“打开”使用Proc.new或Kernel.proc实例化的Proc的严格执行,这样它的行为就像用lambda实例化的Proc?

我的初始化方法采用块和操作并将其分配给实例变量.我希望动作严格执行arity,所以当我稍后向它应用参数时,它会引发一个ArgumentError,我可以挽救并引发一个更有意义的异常.基本上:

class Command
  attr_reader :name,:action

  def initialize(name,&action)
    @name   = name
    @action = action
  end

  def perform(*args)
    begin
      action.call(*args)
    rescue ArgumentError
      raise(WrongArity.new(args.size))
    end
  end
end

class WrongArity < StandardError; end

不幸的是,默认情况下,操作不会强制执行arity:

c = Command.new('second_argument') { |_,y| y }
c.perform(1) # => nil

action.to_proc不起作用,也不起作用(& action).

还有其他想法吗?或者更好地解决问题?

谢谢!

解决方法

你的@action将是一个Proc实例,Procs有一个 arity方法,所以你可以检查该块应该有多少个参数:
def perform(*args)
  if args.size != @action.arity
    raise WrongArity.new(args.size)
  end
  @action.call(*args)
end

那应该照顾像{| a |这样的无拼接块……}和{| a,b | ……}但是随着splats事情有点复杂.如果您有像{| * a |这样的块…}然后@ action.arity将为-1和{| a,* b | ……}会给你一个-2的智商.具有arity -1的块可以使用任意数量的参数(包括无参数),具有arity -2的块至少需要一个参数但可以使用更多参数,依此类推. splatless测试的简单修改应该照顾splatful块:

def perform(*args)
  if @action.arity >= 0 && args.size != @action.arity
    raise WrongArity.new(args.size)
  elsif @action.arity < 0 && args.size < -(@action.arity + 1)
    raise WrongArity.new(args.size)
  end
  @action.call(*args)
end
原文链接:https://www.f2er.com/ruby/265207.html

猜你在找的Ruby相关文章