我目前在ruby程序中使用以下代码来评估传递给方法的变量长度参数。该程序正在运行,但我想知道是否有一个简短的方法来写这个。 应该在我的原始描述中更具体,尝试重写Array类的Inject方法(因此诙谐的名字......)
因此,它需要能够接受最多两个args,如果给出一个块,则最少为0。
要处理的最困难的案例是第一个和第四个,其中1个arg可以是Fixnum或Symbol。如上所述,代码可以工作,只是想找到整理它的方法。
class Array
def enjict(*args)
if args.length == 2 && args[0].is_a?(Fixnum) && args[1].is_a?(Symbol)
start, symbol = args
elsif args.length == 1
raise ArgumentError unless args.first.is_a?(Symbol) || args.first.is_a?(Fixnum)
symbol = args.first if args.first.is_a?(Symbol)
start = args.first if args.first.is_a?(Fixnum)
else
raise ArgumentError unless block_given?
end
copiedArray = dup
start = copiedArray.shift unless start
if block_given?
copiedArray.each { |num| start = yield(start, num) }
else
copiedArray.each { |num| start = start.send(symbol, num) }
end
start
end
end
答案 0 :(得分:2)
可悲的事实是:它很乱,你无能为力。几乎所有Ruby实现都实现Enumerable#inject
具有对解释器内部的特权访问,包括对参数的内省。 MRI,YARV,MRuby在C中实现它,在Objective-C中使用MacRuby和RubyMotion,在Java中使用XRuby和JRuby,在C#中使用Ruby.NET和IronRuby,在RPython中使用Topaz,在PIR中使用Cardinal,等等。
这是Ruby代码根本无法使用的东西。
您可以使用类似的技巧(ab)使用以下事实:可选参数的默认参数表达式可以是任意任意复杂的Ruby表达式,并且这些表达式的局部变量成为局部变量方法。这是判断参数是否通过的常用技巧:
def inject(initial=(no_initial = true; nil), sym=(no_sym = true; nil))
sym, initial = initial, nil if !block_given && no_sym
# and so on …
end
答案 1 :(得分:1)
从条件来看,如何将方法参数重构为:
def enjict(start, symbol, *options, &block)
e = proc{ raise ArgumentError if options.length > 0 && !block_given? }
e.call
if start.is_a?(Fixnum) && symbol.is_a?(Symbol)
# do something you want
else
e.call
end
end