From: "Eregon (Benoit Daloze) via ruby-core" Date: 2023-01-03T13:41:33+00:00 Subject: [ruby-core:111602] [Ruby master Feature#19300] Move public methods from Kernel to Object Issue #19300 has been updated by Eregon (Benoit Daloze). zverok (Victor Shepelev) wrote in #note-7: > The mental model of "you look in `Kernel` to see 'global' methods available everywhere without a receiver, you look in `Object` to see generic methods every object has" is of tremendous significance, even if it doesn't correspond to reality. I agree separating those somehow makes sense. Although it could be done in the same page and just list all public and all private methods separately, isn't it? The fact visibility is not shown properly at https://docs.ruby-lang.org/en/master/Kernel.html is part of the issue. Like `Public Instance Methods` - `#Array`, that's wrong. When I look at https://docs.ruby-lang.org/en/master/Kernel.html https://docs.ruby-lang.org/en/master/Object.html I see a tremendous mess I would never be able to make sense of. For instance the Kernel.html page has both `frozen?` and `require` in the same section, that's confusing, and I guess another case like you mentioned above. I can see your POV now. So I'm against more hacks in RDoc to fix this inconsistency in the short term. I do think pretending methods are in Object instead of Kernel hurts than it helps, but indeed, there also needs to be a clear split between public and private (with receiver/receives-less) instance methods of Kernel. > Otherwise, it is incredibly confusing to see them in the same module: like, it will tell you, "every object has `puts` and `class`", because that's actually **a lie** in the meaning of usage. `puts` as private, `class` as public, that tells you whether you should use a receiver or not. ---------------------------------------- Feature #19300: Move public methods from Kernel to Object https://bugs.ruby-lang.org/issues/19300#change-100972 * Author: zverok (Victor Shepelev) * Status: Rejected * Priority: Normal ---------------------------------------- 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` ```ruby class A def foo = puts "foo" end a = A.new a.foo # prints "foo" a.puts 'bar' # private method `puts' called for # (NoMethodError) ``` There are, though, exactly three (if I am not missing something) methods that, **according to documentation**, break this intuition and belong to [Kernel](https://docs.ruby-lang.org/en/master/Kernel.html): * `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](https://docs.ruby-lang.org/en/master/Kernel.html#method-i-clone) and [Object#dup](https://docs.ruby-lang.org/en/master/Object.html#method-i-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: ```ruby 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: 1. Does this disposition has some internal sense, or it is more of a historical thing? 2. Can it be changed so that public methods belonged to `Object` instead of `Kernel`? 3. If the answer to (2) is "no", can at least docs for `clone`, `tap` and `then` be adjusted to follow other public methods in pretending they are `Object`'s features? -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/