Feature #11781
openWould it be possible to alias .prepend() towards .unshift() for class Array by default?
Description
Hello.
For Strings we can do:
abc = 'world!'
abc[0,0] = 'Hello '
abc # => "Hello world!"
For Arrays we can do:
abc = ['world!']
abc[0,0] = 'Hello '
abc # => ["Hello ", "world!"]
This is nice.
For Strings we can also use .prepend() to add to the beginning.
For Arrays, we have to use .unshift().
I have a hard time remembering .unshift though, .prepend() seems
to be easier for me to remember.
I'd like to use both .prepend for Strings and Arrays; right now
I have to use different names. I could alias prepend to unshift
for class Array, but then I'd have to carry these modifications
into my projects, which is not so good - I would prefer to just
stick to what MRI is doing.
Could we have the alias .prepend() for class Array, meaning
.unshift() too? That way I could use .prepend() for both Arrays
and Strings.
Thanks for reading!
Updated by danielpclark (Daniel P. Clark) almost 10 years ago
prepend
is already a keyword in the Ruby language for prepending a module in the ancestry chain: http://ruby-doc.org/core-2.2.3/Module.html#method-i-prepend
Updated by matz (Yukihiro Matsumoto) almost 10 years ago
It sounds nice. Since it is right before 2.3 release, it may be too late for it.
Matz.
Updated by normalperson (Eric Wong) almost 10 years ago
I prefer we avoid introducing needless aliases.
It increases human cognitive overhead for reviewing/auditing
code and also wastes machine memory + CPU cycles at startup.
Updated by nobu (Nobuyoshi Nakada) almost 10 years ago
Their arities differ.
Let String#prepend
take any number of arguments?
diff --git i/array.c w/array.c
index dd14837..b98142d 100644
--- i/array.c
+++ w/array.c
@@ -5832,6 +5832,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
+ rb_define_method(rb_cArray, "prepend", rb_ary_unshift_m, -1);
rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
rb_define_method(rb_cArray, "each", rb_ary_each, 0);
rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
diff --git i/string.c w/string.c
index e6df91d..d0f6454 100644
--- i/string.c
+++ w/string.c
@@ -2691,21 +2691,28 @@ rb_str_concat(VALUE str1, VALUE str2)
/*
* call-seq:
- * str.prepend(other_str) -> str
+ * str.prepend(other_str, ...) -> str
*
* Prepend---Prepend the given string to <i>str</i>.
*
* a = "world"
* a.prepend("hello ") #=> "hello world"
* a #=> "hello world"
+ *
+ * a = "world"
+ * a.prepend("hello", " ") #=> "hello world"
+ * a #=> "hello world"
*/
static VALUE
-rb_str_prepend(VALUE str, VALUE str2)
+rb_str_prepend(int argc, VALUE *argv, VALUE str)
{
- StringValue(str2);
- StringValue(str);
- rb_str_update(str, 0L, 0L, str2);
+ int i;
+ for (i = argc; i > 0;) {
+ VALUE str2 = argv[--i];
+ StringValue(str2);
+ rb_str_update(str, 0L, 0L, str2);
+ }
return str;
}
@@ -9379,7 +9386,8 @@ Init_String(void)
rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
rb_define_method(rb_cString, "concat", rb_str_concat, 1);
rb_define_method(rb_cString, "<<", rb_str_concat, 1);
- rb_define_method(rb_cString, "prepend", rb_str_prepend, 1);
+ rb_define_method(rb_cString, "prepend", rb_str_prepend, -1);
+ rb_define_method(rb_cString, "unshift", rb_str_prepend, -1);
rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
rb_define_method(rb_cString, "intern", rb_str_intern, 0); /* in symbol.c */
rb_define_method(rb_cString, "to_sym", rb_str_intern, 0); /* in symbol.c */
diff --git i/test/ruby/test_string.rb w/test/ruby/test_string.rb
index eed7c69..853ef7c 100644
--- i/test/ruby/test_string.rb
+++ w/test/ruby/test_string.rb
@@ -2194,6 +2194,14 @@
a.prepend(b)
assert_equal(S("hello world"), a)
assert_equal(S("hello "), b)
+
+ a = S("world")
+ b = S("hel")
+ c = S("lo ")
+ a.prepend(b, c)
+ assert_equal(S("hello world"), a)
+ assert_equal(S("hel"), b)
+ assert_equal(S("lo "), c)
end
def u(str)
Updated by sawa (Tsuyoshi Sawada) almost 10 years ago
String#prepend
and String#concat
are a pair that work similarly (with just the difference on where the new substring is inserted). And since there is already Array#concat
, introducing Array#prepend
would suggest that they should work similarly. However, while Array#concat
takes an array and uses that as sub-array of the original array, the proposed Array#prepend
takes an object and uses that as an element of the original array. This is confusing. I don't think the proposal is good.
Updated by matthewd (Matthew Draper) almost 10 years ago
I too would expect Array#prepend
to be the opposite of Array#concat
, taking other_ary
as a parameter, because that seems to more closely match the relationship between String#prepend
and String#concat
.
It sounds potentially useful in its own right.