Bug 4761 – std.array.mul()

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-08-29T15:31:00Z
Last change time
2016-08-20T12:09:10Z
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2010-08-29T15:31:21Z
In Python I use very often the * (__mul__) list operator, it's handy in many situations (it is not lazy): >>> "abc" * -1 '' >>> "abc" * 0 '' >>> "abc" * 1 'abc' >>> "abc" * 5 'abcabcabcabcabc' >>> [0] * 5 [0, 0, 0, 0, 0] It's not a good idea to add a similar product operator to D arrays because despite vector mult operation will probably require [] (while the mul doesn't require it), the two are too much syntactically close, they risk being too much bug-prone. So I suggest to simply add this mul() to std.array (this must be eager, not a lazy range, otherwise it's not handy for its purposes): /// ... T[] mul(T)(T[] items, int times) { T[] result; static if(!is( typeof(items) == void[] )) { if (times > 0 && items.length > 0) { if (items.length == 1) { result.length = times; result[] = items[0]; } else { result.length = items.length * times; for (size_t pos; pos < result.length; pos += items.length) result[pos .. pos+items.length] = items; } } } return result; } // demo ---------- import std.stdio; void main() { auto a1 = [0].mul(10); writeln(a1); auto a2 = [0, 5, 10].mul(4); writeln(a2); } More unittests and a ddoct on request.
Comment #1 by bearophile_hugs — 2010-08-29T15:44:13Z
This mul() needs more work, to be used on const arrays too. If you are interested, I may try to write this improvement. If the given array is one of the string types, it has to call std.string.repeat() inside. But the second argument of std.string.repeat() must become a signed integer, otherwise you just need repeat("ab", -1) to create a crash.
Comment #2 by bearophile_hugs — 2010-09-01T14:35:02Z
A more general version: import std.traits: isArray, Unqual; /// ... T mul(T)(T items, int times) if(isArray!T) { alias Unqual!(typeof(items[0])) E; // dangerous? E[] result; static if(!is( typeof(items) == void[] )) { if (times > 0 && items.length > 0) { if (items.length == 1) { result.length = times; result[] = items[0]; } else { result.length = items.length * times; for (size_t pos; pos < result.length; pos += items.length) result[pos .. pos+items.length] = items[]; } } } return cast(T)result; // assumeUnique? } unittest { assert("".mul(-10) == ""); assert("".mul(0) == ""); assert("".mul(1) == ""); assert("".mul(10) == ""); assert("a".mul(-10) == ""); assert("a".mul(0) == ""); assert("a".mul(1) == "a"); assert("a".mul(10) == "aaaaaaaaaa"); assert("abc".mul(-10) == ""); assert("abc".mul(0) == ""); assert("abc".mul(1) == "abc"); assert("abc".mul(4) == "abcabcabcabc"); assert(""w.mul(-10) == ""w); assert(""w.mul(0) == ""w); assert(""w.mul(1) == ""w); assert(""w.mul(10) == ""w); assert("a"w.mul(-10) == ""w); assert("a"w.mul(0) == ""w); assert("a"w.mul(1) == "a"w); assert("a"w.mul(10) == "aaaaaaaaaa"w); assert("abc"w.mul(-10) == ""w); assert("abc"w.mul(0) == ""w); assert("abc"w.mul(1) == "abc"w); assert("abc"w.mul(4) == "abcabcabcabc"w); assert(""d.mul(-10) == ""d); assert(""d.mul(0) == ""d); assert(""d.mul(1) == ""d); assert(""d.mul(10) == ""d); assert("a"d.mul(-10) == ""d); assert("a"d.mul(0) == ""d); assert("a"d.mul(1) == "a"d); assert("a"d.mul(10) == "aaaaaaaaaa"d); assert("abc"d.mul(-10) == ""d); assert("abc"d.mul(0) == ""d); assert("abc"d.mul(1) == "abc"d); assert("abc"d.mul(4) == "abcabcabcabc"d); assert((new int[0]).mul(-10) == (new int[0])); assert((new int[0]).mul(0) == (new int[0])); assert((new int[0]).mul(1) == (new int[0])); assert((new int[0]).mul(10) == (new int[0])); assert([1].mul(-10) == (new int[0])); assert([1].mul(0) == (new int[0])); assert([1].mul(1) == [1]); assert([1].mul(5) == [1,1,1,1,1]); assert([1.5,2.3,3.1].mul(-10) == (new double[0])); assert([1.5,2.3,3.1].mul(0) == (new double[0])); assert([1.5,2.3,3.1].mul(1) == [1.5,2.3,3.1]); assert([1.5,2.3,3.1].mul(2) == [1.5,2.3,3.1,1.5,2.3,3.1]); const int[] a1; assert(a1.mul(-10) == a1); assert(a1.mul(0) == a1); assert(a1.mul(1) == a1); assert(a1.mul(10) == a1); const int[] a2 = [1]; assert(a2.mul(-10) == a1); assert(a2.mul(0) == a1); assert(a2.mul(1) == a2); assert(a2.mul(5) == [1,1,1,1,1]); const int[] a3 = [1, 2, 3]; assert(a3.mul(-10) == a1); assert(a3.mul(0) == a1); assert(a3.mul(1) == a3); assert(a3.mul(4) == [1,2,3,1,2,3,1,2,3,1,2,3]); static assert(is(typeof(a3.mul(4)) == const int[])); immutable int[] a4; assert(a4.mul(-10) == a4); assert(a4.mul(0) == a4); assert(a4.mul(1) == a4); assert(a4.mul(10) == a4); immutable int[] a5 = [1]; assert(a5.mul(-10) == a4); assert(a5.mul(0) == a4); assert(a5.mul(1) == a5); assert(a5.mul(5) == [1,1,1,1,1]); immutable int[] a6 = [1, 2, 3]; assert(a6.mul(-10) == a4); assert(a6.mul(0) == a4); assert(a6.mul(1) == a6); assert(a6.mul(4) == [1,2,3,1,2,3,1,2,3,1,2,3]); static assert(is(typeof(a6.mul(4)) == immutable int[])); immutable(int)[] a7 = [1, 2, 3]; static assert(is(typeof(a7.mul(0)) == immutable(int)[])); static assert(is(typeof(a7.mul(1)) == immutable(int)[])); static assert(is(typeof(a7.mul(3)) == immutable(int)[])); } void main() {}
Comment #3 by hsteoh — 2015-08-22T15:26:33Z
Isn't this adequately covered by `std.array.replicate`?
Comment #4 by cauterite — 2016-08-19T22:33:34Z
Surely this issue can be closed now. As has been said already, replicate does pretty much exactly what is proposed here.
Comment #5 by greeenify — 2016-08-20T12:09:10Z
I am closing this as replicate seems to do exactly what you was asked for. Vector operations are out of scope anyways and require a uniform interface. Feel free to reopen of you disagree.