digitalmars.D.learn - Templates: Array slices not recognized
- Chris (33/33) Apr 18 2015 The following:
- Max Klyga (6/51) Apr 18 2015 a[0..5] is an R-value, and cannot be passed by reference.
- Chris (3/54) Apr 18 2015 Doh! You're right! My bad. However, this makes the function less
- ketmar (2/4) Apr 18 2015 maybe `auto ref` can help here?=
- Chris (7/12) Apr 20 2015 Yes, auto ref does the trick. I prefer it to passing the slice by
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (3/17) Apr 20 2015 Strings are slices, too. `string` is equivalent to
The following: import std.stdio : writefln; import std.range.primitives : isInputRange, hasLength; void main() { size_t[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; doSomething(a); // works doSomething(a[0..5]); // ---> Error: template slices.doSomething cannot deduce function from argument types !()(ulong[]), candidates are: // slices.d(11): slices.doSomething(R)(ref R r) if (isInputRange!R && hasLength!R) doSomething!(size_t[])(a[0..5]); // ---> Error: doSomething (ref ulong[] r) is not callable using argument types (ulong[]) } void doSomething(R)(ref R r) if (isInputRange!R && hasLength!R) // etc.. { foreach (ref n; r) { writefln("%d * 2 = %d", n, n * 2); } } //EOF a[0..5] is not recognized as size_t[]. If I give the compiler a hint with !(size_t[]), it complains again, i.e. I can not pass the slice as a reference. A workaround is size_t[] b = a[0..5]; doSomething(b); However, this comes with a serious performance penalty in for loops (even if I predefine b and reuse it in the loop). to!(size_t[])(a[0..5]) is even worse. Any thoughts or tips?
Apr 18 2015
On 2015-04-18 13:46:19 +0000, Chris said:The following: import std.stdio : writefln; import std.range.primitives : isInputRange, hasLength; void main() { size_t[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; doSomething(a); // works doSomething(a[0..5]); // ---> Error: template slices.doSomething cannot deduce function from argument types !()(ulong[]), candidates are: // slices.d(11): slices.doSomething(R)(ref R r) if (isInputRange!R && hasLength!R) doSomething!(size_t[])(a[0..5]); // ---> Error: doSomething (ref ulong[] r) is not callable using argument types (ulong[]) } void doSomething(R)(ref R r) if (isInputRange!R && hasLength!R) // etc.. { foreach (ref n; r) { writefln("%d * 2 = %d", n, n * 2); } } //EOF a[0..5] is not recognized as size_t[]. If I give the compiler a hint with !(size_t[]), it complains again, i.e. I can not pass the slice as a reference. A workaround is size_t[] b = a[0..5]; doSomething(b); However, this comes with a serious performance penalty in for loops (even if I predefine b and reuse it in the loop). to!(size_t[])(a[0..5]) is even worse. Any thoughts or tips?a[0..5] is an R-value, and cannot be passed by reference. As you noticed, once you use a variable - everything works because only L-values can be passed by reference. Also why are you passing slices by reference? Slices do not copy the memory they point to when passed by value.
Apr 18 2015
On Saturday, 18 April 2015 at 16:26:57 UTC, Max Klyga wrote:On 2015-04-18 13:46:19 +0000, Chris said:The following: import std.stdio : writefln; import std.range.primitives : isInputRange, hasLength; void main() { size_t[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; doSomething(a); // works doSomething(a[0..5]); // ---> Error: template slices.doSomething cannot deduce function from argument types !()(ulong[]), candidates are: // slices.d(11): slices.doSomething(R)(ref R r) if (isInputRange!R && hasLength!R) doSomething!(size_t[])(a[0..5]); // ---> Error: doSomething (ref ulong[] r) is not callable using argument types (ulong[]) } void doSomething(R)(ref R r) if (isInputRange!R && hasLength!R) // etc.. { foreach (ref n; r) { writefln("%d * 2 = %d", n, n * 2); } }Doh! You're right! My bad. However, this makes the function less generic, but it doesn't matter here.//EOF a[0..5] is not recognized as size_t[]. If I give the compiler a hint with !(size_t[]), it complains again, i.e. I can not pass the slice as a reference. A workaround is size_t[] b = a[0..5]; doSomething(b); However, this comes with a serious performance penalty in for loops (even if I predefine b and reuse it in the loop). to!(size_t[])(a[0..5]) is even worse. Any thoughts or tips?a[0..5] is an R-value, and cannot be passed by reference. As you noticed, once you use a variable - everything works because only L-values can be passed by reference. Also why are you passing slices by reference? Slices do not copy the memory they point to when passed by value.
Apr 18 2015
On Sat, 18 Apr 2015 17:50:56 +0000, Chris wrote:Doh! You're right! My bad. However, this makes the function less generic, but it doesn't matter here.maybe `auto ref` can help here?=
Apr 18 2015
On Saturday, 18 April 2015 at 17:59:19 UTC, ketmar wrote:On Sat, 18 Apr 2015 17:50:56 +0000, Chris wrote:Yes, auto ref does the trick. I prefer it to passing the slice by value, because I can extend the function to cater for more types. My implementation (which is different from the one posted above) works also with strings, for example. Anyway, it gave me a performance boost of ~2.7 times as compared to the workarounds I had. This was well worth it!Doh! You're right! My bad. However, this makes the function less generic, but it doesn't matter here.maybe `auto ref` can help here?
Apr 20 2015
On Monday, 20 April 2015 at 09:07:54 UTC, Chris wrote:On Saturday, 18 April 2015 at 17:59:19 UTC, ketmar wrote:Strings are slices, too. `string` is equivalent to `immutable(char)[]`.On Sat, 18 Apr 2015 17:50:56 +0000, Chris wrote:Yes, auto ref does the trick. I prefer it to passing the slice by value, because I can extend the function to cater for more types. My implementation (which is different from the one posted above) works also with strings, for example. Anyway, it gave me a performance boost of ~2.7 times as compared to the workarounds I had. This was well worth it!Doh! You're right! My bad. However, this makes the function less generic, but it doesn't matter here.maybe `auto ref` can help here?
Apr 20 2015
On Monday, 20 April 2015 at 09:58:06 UTC, Marc Schütz wrote:On Monday, 20 April 2015 at 09:07:54 UTC, Chris wrote:I know. My function returns an array of the same type (size_t[] or a string (immutable(char)[] or whatever). With auto ref I can pass a string without having to slice it, like so string a = "bla"; string b = "blub"; auto res = doSomething(a, b); If I didn't use "auto ref" or "ref", string would get copied, wouldn't it? auto ref doSomething(R needle, R haystack); To avoid this, I would have to write a[0..$], b[0..$], which is not nice. Right or wrong? For the record, I put the function inside a struct which again boosted the performance. No it is faster by a factor of ~3.17. Using the struct is even slightly faster than executing the same code directly within the for loop. That surprised me.On Saturday, 18 April 2015 at 17:59:19 UTC, ketmar wrote:Strings are slices, too. `string` is equivalent to `immutable(char)[]`.On Sat, 18 Apr 2015 17:50:56 +0000, Chris wrote:Yes, auto ref does the trick. I prefer it to passing the slice by value, because I can extend the function to cater for more types. My implementation (which is different from the one posted above) works also with strings, for example. Anyway, it gave me a performance boost of ~2.7 times as compared to the workarounds I had. This was well worth it!Doh! You're right! My bad. However, this makes the function less generic, but it doesn't matter here.maybe `auto ref` can help here?
Apr 20 2015
On Mon, 20 Apr 2015 10:14:25 +0000, Chris wrote:string a =3D "bla"; string b =3D "blub"; =20 auto res =3D doSomething(a, b); =20 If I didn't use "auto ref" or "ref", string would get copied, wouldn't it?no, it wont -- not unless you'll append something to it. slicing arrays=20 (and string is array too) will never copy anything.=
Apr 20 2015
On Monday, 20 April 2015 at 10:14:27 UTC, Chris wrote:string a = "bla"; string b = "blub"; auto res = doSomething(a, b); If I didn't use "auto ref" or "ref", string would get copied, wouldn't it? auto ref doSomething(R needle, R haystack); To avoid this, I would have to write a[0..$], b[0..$], which is not nice. Right or wrong?Wrong. `a[0..$]` is the same as simply `a`. A `string` is just another slice: a pointer and a length.
Apr 20 2015
On Monday, 20 April 2015 at 10:27:00 UTC, anonymous wrote:On Monday, 20 April 2015 at 10:14:27 UTC, Chris wrote:Ah, I see. So strings don't get copied around and I can remove ref, very good.string a = "bla"; string b = "blub"; auto res = doSomething(a, b); If I didn't use "auto ref" or "ref", string would get copied, wouldn't it? auto ref doSomething(R needle, R haystack); To avoid this, I would have to write a[0..$], b[0..$], which is not nice. Right or wrong?Wrong. `a[0..$]` is the same as simply `a`. A `string` is just another slice: a pointer and a length.
Apr 20 2015
On Monday, 20 April 2015 at 10:42:54 UTC, Chris wrote:On Monday, 20 April 2015 at 10:27:00 UTC, anonymous wrote:For the record. I mixed up the results there. The code executed directly in the for loop is faster than using a struct, it's also faster than using a mixin template (around 10 msecs). My apologies.On Monday, 20 April 2015 at 10:14:27 UTC, Chris wrote:Ah, I see. So strings don't get copied around and I can remove ref, very good.string a = "bla"; string b = "blub"; auto res = doSomething(a, b); If I didn't use "auto ref" or "ref", string would get copied, wouldn't it? auto ref doSomething(R needle, R haystack); To avoid this, I would have to write a[0..$], b[0..$], which is not nice. Right or wrong?Wrong. `a[0..$]` is the same as simply `a`. A `string` is just another slice: a pointer and a length.
Apr 20 2015