为什么在String对象上调用参数方法时Ruby输出[[:rest]]?
Why Ruby outputs [[:rest]] when the parameter method is called on String objects?
我在 jruby irb 上玩耍时遇到了这种现象,其中参数方法 returns [[:rest]]
在字符串方法上调用时。
这不仅是字符串的情况,我还要举一个关于字符串的例子。
irb(main):042:0> String.new.methods-Object.methods
[:valid_encoding?, :casecmp, :to_java_bytes, :squeeze!,
:is_utf8?, :slice, :hex, :[]=, :initialize_copy, :empty?,
:oct, :rindex, :unseeded_hash, :%, :rjust, :chop, :index,
:gsub!, :chomp!, :*, :+, :concat, :capitalize, :singularize,
:titlecase, :each_line, :size, :deconstantize, :downcase!,
:capitalize!, :to_sym, :humanize, :setbyte, :force_encoding,
:sub, :reverse!, :swapcase, :scan, :gsub, :sum, :partition,
:to_str, :codepoints, :swapcase!, :byteslice, :end_with?,
:upto, :tr!, :[], :intern, :parameterize, :tableize, :chomp,
:pluralize, :reverse, :mb_chars, :succ, :underscore, :titleize,
:start_with?, :ljust, :tr, :chars, :chop!, :encode, :<<,
:lstrip!, :dasherize, :prepend, :replace, :strip, :split,
:to_i, :succ!, :to_f, :to_r, :rstrip!, :count, :to_c, :chr,
:encoding, :camelcase, :slice!, :next!, :upcase, :bytesize,
:demodulize, :delete!, :each_byte, :next, :classify, :squeeze,
:downcase, :tr_s, :constantize, :crypt, :each_codepoint,
:foreign_key, :insert, :delete, :camelize, :upcase!, :getbyte,
:rpartition, :sub!, :unpack, :dump, :lines, :strip!, :ord,
:safe_constantize, :center, :each_char, :match, :clear,
:length, :to_java_string, :rstrip, :bytes, :ascii_only?,
:tr_s!, :encode!, :lstrip, :to_json_raw, :to_json_raw_object,
:included, :between?]
如您所见,上面的列表显示了字符串 class 中的方法,当对上述任何方法调用参数方法时,它会给出输出 # => [[:rest]]
irb(main):043:0> String.new.method(:each_line).parameters
[[:rest]]
irb(main):044:0> String.new.method(:slice).parameters
[[:rest]]
gem 名为 Sidekiq
的另一个示例。在这种情况下,它显示方法 class 名称 Stats
以及 rest
.
irb(main):049:0> Sidekiq::Stats.new.methods-Object.methods
[:scheduled_size, :enqueued, :failed, :processed, :default_queue_latency, :retry_size, :queues, :processes_size, :reset, :workers_size, :dead_size, :fetch_stats!]
irb(main):050:0> Sidekiq::Stats.new.method(:reset).parameters
[[:rest, :stats]]
谁能解释一下 rest
在这种情况下指的是什么?
parameters
会给你一个数组对,第一个元素是一种参数类型,第二个元素是接受它的变量的名称。大多数参数的类型为 :req
,这是一个必需的变量。可选参数,具有默认值的参数,类型为 :opt
。使用 splat 定义的参数具有 :rest
类型:这些参数将吸收除必需参数和可选参数之外的任何其他参数。还有新的 :keyrest
,它是 doubly-splat 参数。
def foo(a, b=3, *c, **d); end
method(:foo).parameters
# => [[:req, :a], [:opt, :b], [:rest, :c], [:keyrest, :d]]
如果其余参数未命名,您只会得到 :rest
值而不是一对:
def bar(a, b=3, *); end
method(:foo).parameters
# => [[:req, :a], [:opt, :b], [:rest]]
许多 Ruby 本机实现的方法没有用精确的签名定义;底层 C 代码正在检查参数列表以确定调用了该方法的哪个用例。因此,在 Ruby 中,String#each_line
通常是这样的:
class String
def each_line(separator=$/)
#...
end
end
这会给它签名[[:opt, :separator]]
,它实际上被定义为好像它写成
class String
def each_line(*)
#...
end
end
我在 jruby irb 上玩耍时遇到了这种现象,其中参数方法 returns [[:rest]]
在字符串方法上调用时。
这不仅是字符串的情况,我还要举一个关于字符串的例子。
irb(main):042:0> String.new.methods-Object.methods
[:valid_encoding?, :casecmp, :to_java_bytes, :squeeze!,
:is_utf8?, :slice, :hex, :[]=, :initialize_copy, :empty?,
:oct, :rindex, :unseeded_hash, :%, :rjust, :chop, :index,
:gsub!, :chomp!, :*, :+, :concat, :capitalize, :singularize,
:titlecase, :each_line, :size, :deconstantize, :downcase!,
:capitalize!, :to_sym, :humanize, :setbyte, :force_encoding,
:sub, :reverse!, :swapcase, :scan, :gsub, :sum, :partition,
:to_str, :codepoints, :swapcase!, :byteslice, :end_with?,
:upto, :tr!, :[], :intern, :parameterize, :tableize, :chomp,
:pluralize, :reverse, :mb_chars, :succ, :underscore, :titleize,
:start_with?, :ljust, :tr, :chars, :chop!, :encode, :<<,
:lstrip!, :dasherize, :prepend, :replace, :strip, :split,
:to_i, :succ!, :to_f, :to_r, :rstrip!, :count, :to_c, :chr,
:encoding, :camelcase, :slice!, :next!, :upcase, :bytesize,
:demodulize, :delete!, :each_byte, :next, :classify, :squeeze,
:downcase, :tr_s, :constantize, :crypt, :each_codepoint,
:foreign_key, :insert, :delete, :camelize, :upcase!, :getbyte,
:rpartition, :sub!, :unpack, :dump, :lines, :strip!, :ord,
:safe_constantize, :center, :each_char, :match, :clear,
:length, :to_java_string, :rstrip, :bytes, :ascii_only?,
:tr_s!, :encode!, :lstrip, :to_json_raw, :to_json_raw_object,
:included, :between?]
如您所见,上面的列表显示了字符串 class 中的方法,当对上述任何方法调用参数方法时,它会给出输出 # => [[:rest]]
irb(main):043:0> String.new.method(:each_line).parameters
[[:rest]]
irb(main):044:0> String.new.method(:slice).parameters
[[:rest]]
gem 名为 Sidekiq
的另一个示例。在这种情况下,它显示方法 class 名称 Stats
以及 rest
.
irb(main):049:0> Sidekiq::Stats.new.methods-Object.methods
[:scheduled_size, :enqueued, :failed, :processed, :default_queue_latency, :retry_size, :queues, :processes_size, :reset, :workers_size, :dead_size, :fetch_stats!]
irb(main):050:0> Sidekiq::Stats.new.method(:reset).parameters
[[:rest, :stats]]
谁能解释一下 rest
在这种情况下指的是什么?
parameters
会给你一个数组对,第一个元素是一种参数类型,第二个元素是接受它的变量的名称。大多数参数的类型为 :req
,这是一个必需的变量。可选参数,具有默认值的参数,类型为 :opt
。使用 splat 定义的参数具有 :rest
类型:这些参数将吸收除必需参数和可选参数之外的任何其他参数。还有新的 :keyrest
,它是 doubly-splat 参数。
def foo(a, b=3, *c, **d); end
method(:foo).parameters
# => [[:req, :a], [:opt, :b], [:rest, :c], [:keyrest, :d]]
如果其余参数未命名,您只会得到 :rest
值而不是一对:
def bar(a, b=3, *); end
method(:foo).parameters
# => [[:req, :a], [:opt, :b], [:rest]]
许多 Ruby 本机实现的方法没有用精确的签名定义;底层 C 代码正在检查参数列表以确定调用了该方法的哪个用例。因此,在 Ruby 中,String#each_line
通常是这样的:
class String
def each_line(separator=$/)
#...
end
end
这会给它签名[[:opt, :separator]]
,它实际上被定义为好像它写成
class String
def each_line(*)
#...
end
end