[ruby-core:77068] [Ruby trunk Feature#12697] Why shouldn't Module meta programming methods be public?
From:
ruby-core@...
Date:
2016-08-25 18:44:25 UTC
List:
ruby-core #77068
Issue #12697 has been updated by Marc-Andre Lafortune.
Hi,
As stated by bughit, a typical case where we have to resort to `send` for these is in meta programming, say:
def self.included(base)
base.send(:define_method, :foo) { ... } unless base.column_names.include?(:foo)
end
Yukihiro Matsumoto wrote:
> I still believe
>
> ```
> class String
> include Term::ANSIColor
> end
> ```
>
> is far better than `String.include Term::ANSIColor`. It is clearer and has more space to optimize.
I respect your opinion. Please realize that not everybody agree with this though. I feel that `String.include Term::ANSIColor` is clearer as it does one and one thing only. It's a single atomic operation. The `class ...` form, for me, means "Reopen the class", followed by "include ANSIColor", followed by "ok, that's actually all we wanted to do for this class".
The same way some people will prefer
if some_condition
do_this_single_thing
end
I usually prefer
do_this_single_thing if some_condition
Typical scenario of a gem: define modules in `lib/my_gem/...`, then in `lib/my_gem.rb`:
require_relative 'lib/...'
String.include MyGem::StringExtension
SomethingElse.extend MyGem::Something
That is my preference over
require_relative 'lib/...'
class String
include MyGem::StringExtension
end
class SomethingElse
extend MyGem::Something
end
Here are some actual examples of other people that feel this way, from a quick github search:
https://github.com/edgecase/authorize_me/blob/4a1ccf42b2d89a53cafbc0cb4ace236b57ba12ea/rails/init.rb
https://github.com/redradiant/centsible/blob/e4cc35ee1ccb8b1e66992bc18a9b7a26643affe4/vendor/bundle/ruby/1.9.1/gems/recaptcha-0.2.3/lib/recaptcha/merb.rb
https://github.com/nbino/eegloo/blob/a51e6ba77616bc4dd84c76bd0bf07f7ada3a7bd7/vendor/plugins/paginating_find/init.rb
https://github.com/mailserv/mailserv/blob/36b9ff211ba71df0b77aa9de2f6382f60787151b/admin/vendor/plugins/spawn/init.rb
etc.
The search returns over 2.6 million hits (but that includes a lot of duplicates): https://github.com/search?utf8=%E2%9C%93&q=send+include+language%3Aruby+&type=Code&ref=searchresults
> Besides that the fact that `include` etc may have huge performance penalty is also a reason to prohibit casual class/module modification.
I'm afraid I don't see this; I feel that if a programmer is calling `include`, then it is because `include` is needed. It will be called no matter what. I doubt this prevented a single misuse of `include`!
> Is there any reason to allow this in addition to saving extra few keystrokes?
As I stated in my original request, I feel that calling `send` is what should be discouraged, not `include`. Using `public_send` is fine, but needing to use `send` means:
- I'm doing something I shouldn't be doing
- I'm calling a method that was not intended for me to call
- this might break or have unintended consequences, now or in the future
But classes are *intended* to be augmented, to have methods defined, to have plugins included in them. We shouldn't have to use `send` to do that.
----------------------------------------
Feature #12697: Why shouldn't Module meta programming methods be public?
https://bugs.ruby-lang.org/issues/12697#change-60290
* Author: bug hit
* Status: Feedback
* Priority: Normal
* Assignee: Yukihiro Matsumoto
----------------------------------------
Methods like alias_method, attr_accessor, define_method, and similar
I don't think Ruby discourages this kind of meta programming, so why make it less convenient, by necessitating `send` or `module_eval`?
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>