Feature #19300
closedMove public methods from Kernel to Object
Description
In my understanding, Kernel
is a container for methods that are perceived as "global", and are available inside every objects as its private methods, like puts
class A
def foo = puts "foo"
end
a = A.new
a.foo # prints "foo"
a.puts 'bar'
# private method `puts' called for #<A:0x00007f39a683db28> (NoMethodError)
There are, though, exactly three (if I am not missing something) methods that, according to documentation, break this intuition and belong to Kernel:
clone
tap
then
All those methods are public method for a receiver, and they mostly make sense with an explicit receiver. The most confusing of them is #clone
, which is close cousin of #dup
, but it is Kernel#clone and Object#dup.
This state of things is mostly harmless in practical code, but very inconvenient for teaching, reasoning about the meaning of modules and objects, and lookup for documentation.
But, in the description above, according to documentation is important statement. Because according to introspection, method definitions are spread differently:
puts "Public"
Object.new
.then { |o| o.methods.group_by { o.method(_1).owner } }
.each { puts "#{_1}: #{_2.sort.join(', ')}" }
puts
puts "Private:"
Object.new
.then { |o| o.private_methods.group_by { o.method(_1).owner } }
.each { puts "#{_1}: #{_2.sort.join(', ')}" }
Output:
Public
Kernel: !~, <=>, ===, class, clone, define_singleton_method, display, dup, enum_for, eql?, extend, freeze, frozen?, hash, inspect, instance_of?, instance_variable_defined?, instance_variable_get, instance_variable_set, instance_variables, is_a?, itself, kind_of?, method, methods, nil?, object_id, private_methods, protected_methods, public_method, public_methods, public_send, remove_instance_variable, respond_to?, send, singleton_class, singleton_method, singleton_methods, tap, then, to_enum, to_s, yield_self
BasicObject: !, !=, ==, __id__, __send__, equal?, instance_eval, instance_exec
Private:
Kernel: Array, Complex, Float, Hash, Integer, Rational, String, __callee__, __dir__, __method__, `, abort, at_exit, autoload, autoload?, binding, block_given?, caller, caller_locations, catch, eval, exec, exit, exit!, fail, fork, format, gem, gem_original_require, gets, global_variables, initialize_clone, initialize_copy, initialize_dup, iterator?, lambda, load, local_variables, loop, open, p, pp, print, printf, proc, putc, puts, raise, rand, readline, readlines, require, require_relative, respond_to_missing?, select, set_trace_func, sleep, spawn, sprintf, srand, syscall, system, test, throw, trace_var, trap, untrace_var, warn
BasicObject: initialize, method_missing, singleton_method_added, singleton_method_removed, singleton_method_undefined
E.g., internally, Object
doesn't have any method defined, and is just a BasicObject
with Kernel
included.
So, there are three questions/proposals:
- Does this disposition has some internal sense, or it is more of a historical thing?
- Can it be changed so that public methods belonged to
Object
instead ofKernel
? - If the answer to (2) is "no", can at least docs for
clone
,tap
andthen
be adjusted to follow other public methods in pretending they areObject
's features?