class.c (append_features): remove the method

The technique is called "double dispatch" (that was popular in
Smalltalk), but it does not work well with mruby. It's slower and
consumes more memory. Even thought `#append_features` defined in ISO
standard (15.2.2.4.11), we decided to remove it. Strictly speaking, it
is mruby limitation. And it should be documented clearly.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-04-23 16:50:08 +09:00
parent 5fe406d59c
commit 9387cd382e
3 changed files with 16 additions and 32 deletions
-11
View File
@@ -12,17 +12,6 @@ class Module
# 15.2.2.4.11
alias attr attr_reader
# 15.2.2.4.27
def include(*args)
args.reverse!
mod = self
args.each do |m|
m.__send__(:append_features, mod)
m.__send__(:included, mod)
end
self
end
def prepend(*args)
args.reverse!
mod = self
+16 -7
View File
@@ -1597,13 +1597,22 @@ mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod)
}
static mrb_value
mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
mrb_mod_include(mrb_state *mrb, mrb_value mod)
{
struct RClass *c;
struct RClass *c = mrb_class_ptr(mod);
mrb_int argc;
mrb_value *argv;
mrb_sym included = MRB_SYM(included);
mrb_check_type(mrb, mod, MRB_TT_MODULE);
mrb_get_args(mrb, "c", &c);
mrb_include_module(mrb, c, mrb_class_ptr(mod));
mrb_get_args(mrb, "*", &argv, &argc);
while (argc--) {
mrb_value m = argv[argc];
mrb_check_type(mrb, m, MRB_TT_MODULE);
mrb_include_module(mrb, c, mrb_class_ptr(m));
if (!mrb_func_basic_p(mrb, m, included, mrb_do_nothing)) {
mrb_funcall_argv(mrb, m, included, 1, &mod);
}
}
return mod;
}
@@ -3160,7 +3169,8 @@ mrb_init_class(mrb_state *mrb)
mrb_define_private_method_id(mrb, mod, MRB_SYM(extended), mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
mrb_define_private_method_id(mrb, mod, MRB_SYM(prepended), mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, mod, MRB_SYM_Q(include), mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
mrb_define_private_method_id(mrb, mod, MRB_SYM(append_features), mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
mrb_define_method_id(mrb, mod, MRB_SYM(include), mrb_mod_include, MRB_ARGS_REQ(1)); /* 15.2.2.4.27 */
mrb_define_private_method_id(mrb, mod, MRB_SYM(prepend_features), mrb_mod_prepend_features, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, mod, MRB_SYM(class_eval), mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */
mrb_define_private_method_id(mrb, mod, MRB_SYM(included), mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
@@ -3192,7 +3202,6 @@ mrb_init_class(mrb_state *mrb)
mrb_define_private_method_id(mrb, mod, MRB_SYM(method_undefined), mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_define_private_method_id(mrb, mod, MRB_SYM(const_added), mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_undef_method_id(mrb, cls, MRB_SYM(append_features));
mrb_undef_method_id(mrb, cls, MRB_SYM(prepend_features));
mrb_undef_method_id(mrb, cls, MRB_SYM(extend_object));
mrb_undef_method_id(mrb, cls, MRB_SYM(module_function));
-14
View File
@@ -56,20 +56,6 @@ assert('Module#ancestors', '15.2.2.4.9') do
assert_true r.include?(Object)
end
assert('Module#append_features', '15.2.2.4.10') do
module Test4AppendFeatures
def self.append_features(mod)
Test4AppendFeatures2.const_set(:Const4AppendFeatures2, mod)
end
end
module Test4AppendFeatures2
include Test4AppendFeatures
end
assert_equal Test4AppendFeatures2, Test4AppendFeatures2.const_get(:Const4AppendFeatures2)
assert_raise(FrozenError) { Module.new.__send__(:append_features,Class.new.freeze) }
end
assert('Module#attr NameError') do
%w[
foo?