在 ruby 中评估 args 的简写方法
Short hand way to evaluate args in ruby
我目前在 ruby 程序中使用以下代码来评估传递给方法的可变长度参数。该程序是 运行 但是我想知道是否有一种简写的方法来编写它。
应该在我的原始描述中更具体,尝试重写数组的 Inject 方法 class(因此是机智的名字...)
因此,它需要能够接受最多两个 args,如果给定一个块,则最少为 0。
- array.inject(:+)
- array.inject{ |输出,数量|输出 + 数字}
- array.inject(arg, :+)
- array.inject(arg) { |输出,数字|输出 + 数字}
最难 case/s 处理的是第一个和第一个参数可以是 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
根据条件判断,如何将您的方法参数重构为:
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
可悲的事实是:它很乱,而且您无能为力。几乎所有 Ruby 实现都在 Enumerable#inject
中实现了对解释器内部结构的特权访问,包括对参数的自省。 MRI、YARV、MRuby用C实现,MacRuby和RubyMotion在Objective-C、XRuby和JRuby在Java、Ruby.NET 和 C# 中的 IronRuby、RPython 中的 Topaz、PIR 中的 Cardinal 等等。
这是 Ruby 代码所不具备的。
仅Rubinius implements it in Ruby.
您可以通过(滥用)使用以下事实来使用类似的技巧:可选参数的默认参数表达式可以是 any 任意复杂的 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
我目前在 ruby 程序中使用以下代码来评估传递给方法的可变长度参数。该程序是 运行 但是我想知道是否有一种简写的方法来编写它。 应该在我的原始描述中更具体,尝试重写数组的 Inject 方法 class(因此是机智的名字...)
因此,它需要能够接受最多两个 args,如果给定一个块,则最少为 0。
- array.inject(:+)
- array.inject{ |输出,数量|输出 + 数字}
- array.inject(arg, :+)
- array.inject(arg) { |输出,数字|输出 + 数字}
最难 case/s 处理的是第一个和第一个参数可以是 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
根据条件判断,如何将您的方法参数重构为:
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
可悲的事实是:它很乱,而且您无能为力。几乎所有 Ruby 实现都在 Enumerable#inject
中实现了对解释器内部结构的特权访问,包括对参数的自省。 MRI、YARV、MRuby用C实现,MacRuby和RubyMotion在Objective-C、XRuby和JRuby在Java、Ruby.NET 和 C# 中的 IronRuby、RPython 中的 Topaz、PIR 中的 Cardinal 等等。
这是 Ruby 代码所不具备的。
仅Rubinius implements it in Ruby.
您可以通过(滥用)使用以下事实来使用类似的技巧:可选参数的默认参数表达式可以是 any 任意复杂的 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