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:
clonetapthen
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
Objectinstead ofKernel? - If the answer to (2) is "no", can at least docs for
clone,tapandthenbe adjusted to follow other public methods in pretending they areObject's features?