Question: Why Ruby outputs [[:rest]] when the parameter method is called on String objects?

Question

Why Ruby outputs [[:rest]] when the parameter method is called on String objects?

Answers 1
Added at 2016-12-13 06:12
Tags
Question

I was playing around on jruby irb and came across this phenomenon where the parameter method returns [[:rest]] when its invoked on a string method. This is not only the case with Strings but I'm gonna give an example regarding strings.

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?]

As you can see the above list shows the methods from the String class, when parameter method is called on any of the above methods it gives the output # => [[:rest]]

irb(main):043:0> String.new.method(:each_line).parameters
[[:rest]]
irb(main):044:0> String.new.method(:slice).parameters
[[:rest]]

Another example in case of a gem named Sidekiq. In this case its showing the methods class name Stats along with 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]]

Can someone explain what rest refers to in this case?

Answers
nr: #1 dodano: 2016-12-13 06:12

parameters will give you an array of pairs, with the first element being a type of parameter, and the second the name of the variable that will accept it. Most parameters have type :req, a required variable. Optional parameters, those with default value, have type :opt. And parameters defined with a splat have the type :rest: those parameters will slurp up any additional parameters beyond the required and optional. There's also the new :keyrest, which is the doubly-splat parameter.

def foo(a, b=3, *c, **d); end
method(:foo).parameters
# => [[:req, :a], [:opt, :b], [:rest, :c], [:keyrest, :d]] 

If the rest parameter is unnamed, you just get the :rest value instead of a pair:

def bar(a, b=3, *); end
method(:foo).parameters
# => [[:req, :a], [:opt, :b], [:rest]]

Many Ruby methods with native implementation were not defined with precise signature; the underlying C code is inspecting the parameter list to determine which use case of the method was invoked. Thus, whereas in Ruby String#each_line would normally be made like this:

class String
  def each_line(separator=$/)
    #...
  end
end

which would give it the signature [[:opt, :separator]], it is actually defined as if it was written like

class String
  def each_line(*)
    #...
  end
end
Source Show
◀ Wstecz