
Issue #20093 has been updated by tagomoris (Satoshi Tagomori). Thank you for your feedback. Yes, `class_eval` / `module_eval` can do the same things functionally. `class extension String` could be a syntax sugar of `String.class_eval do ... end`. I think it's reasonable to have such a syntax sugar because we're using `class Foo; ...; end` instead of `(Foo = Class.new).class_eval do ... end`. I never want to recommend someone to use `class_eval` for monkey patching. As pointed out above, I want to have the more simple keyword `reopen` or `extend`(oops, it's not good) for both class and module (e.g., `reopen String`). But adding top-level keywords is unrealistic. That's the reason I proposed a bit of verbose syntax. ---------------------------------------- Feature #20093: Syntax or keyword to reopen existing classs/modules, never to define new classs/modules https://bugs.ruby-lang.org/issues/20093#change-105879 * Author: tagomoris (Satoshi Tagomori) * Status: Open * Priority: Normal ---------------------------------------- `class A` and `module B` will reopen existing class A or module B to add/re-define methods if A/B exists. Otherwise, these will define the new class/module A/B. But, in my opinion, the code of `class A` for patching existing classes doesn't work expectedly when `A` is not defined beforehand. It expects other codes to define `A` before being called. For example: ```ruby # string_exclude.rb class String def exclude?(string) !include?(string) end end ``` This code expects that there is the `String` class, and it has the `include?` method. This code doesn't work if the file is loaded in the way below: ```ruby load('string_exclude.rb', true) ``` This code doesn't raise errors and will define an almost empty class (only with a method `exclude?` to raise NameError). It should be unexpected for every user. So, I want to propose a new syntax to reopen the existing class/module or raise errors if the specified class/module is not defined. ```ruby class extension String def exclude?(string) !include?(string) end end # adds #exclude? to String class class extension Stroooong def exclude?(string) !include?(string) end end # will raise NameError (or something else) ``` Some additional things: * `class extension String` (and `module extension String`) causes a compile error (SyntaxError) on Ruby 3.3. So we have space to add a keyword between class/module and the class/module name. * I don't have a strong opinion about the keyword name `extension`. An alternative idea is `reopen`. -- https://bugs.ruby-lang.org/