digitalmars.D.learn - Append to 'map' result
- Jean-Louis Leroy (9/9) Jul 04 2017 I want to create a range that consists of the result of a map()
- H. S. Teoh via Digitalmars-d-learn (7/17) Jul 04 2017 [...]
- Jean-Louis Leroy (14/29) Jul 04 2017 Thanks!
- =?UTF-8?Q?Ali_=c3=87ehreli?= (29/60) Jul 04 2017 No time to dig deeper but this is because the two ranges that chain()
- Jean-Louis Leroy (4/10) Jul 04 2017 I suspect that that is the reason, although I checked in several
- =?UTF-8?Q?Ali_=c3=87ehreli?= (45/55) Jul 04 2017 This is related to TypeInfo.init, which unfortunately is *not* the .init...
- Jean-Louis Leroy (18/36) Jul 05 2017 Aaah, so I was not doing anything wrong ;-)
- Nicholas Wilson (4/13) Jul 04 2017 using
- Jonathan M Davis via Digitalmars-d-learn (12/28) Jul 04 2017 Yeah, that will convert the range to a dynamic array, but if you're look...
I want to create a range that consists of the result of a map() followed by a value, e.g.: int[] x = [ 1, 2, 3]; auto y = map!(x => x * x)(x); auto z = y ~ 99; // how??? I have tried several variations: convert 99 to a dynamic array, to a range, convert range to dynamic array (couldn't even figure that one); to no avail. Help please...
Jul 04 2017
On Tue, Jul 04, 2017 at 11:27:25PM +0000, Jean-Louis Leroy via Digitalmars-d-learn wrote:I want to create a range that consists of the result of a map() followed by a value, e.g.: int[] x = [ 1, 2, 3]; auto y = map!(x => x * x)(x); auto z = y ~ 99; // how??? I have tried several variations: convert 99 to a dynamic array, to a range, convert range to dynamic array (couldn't even figure that one); to no avail.[...] Try: auto z = chain(y, only(99)); T -- I don't trust computers, I've spent too long programming to think that they can get anything right. -- James Miller
Jul 04 2017
On Tuesday, 4 July 2017 at 23:26:28 UTC, H. S. Teoh wrote:On Tue, Jul 04, 2017 at 11:27:25PM +0000, Jean-Louis Leroy via Digitalmars-d-learn wrote:Thanks! However, when I try to use this construct in my real code, I still have a problem: // k is a ClassInfo chain(map!(i => i.classinfo)(k.interfaces), only(k.base)) meth.d(311): Error: template std.range.chain cannot deduce function from argument types !()(MapResult!(__lambda3, Interface[]), OnlyResult!(TypeInfo_Class, 1LU)), candidates are: /usr/include/d/std/range/package.d(795): std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void))I want to create a range that consists of the result of a map() followed by a value, e.g.: int[] x = [ 1, 2, 3]; auto y = map!(x => x * x)(x); auto z = y ~ 99; // how??? I have tried several variations: convert 99 to a dynamic array, to a range, convert range to dynamic array (couldn't even figure that one); to no avail.[...] Try: auto z = chain(y, only(99));
Jul 04 2017
On 07/04/2017 04:57 PM, Jean-Louis Leroy wrote:On Tuesday, 4 July 2017 at 23:26:28 UTC, H. S. Teoh wrote:No time to dig deeper but this is because the two ranges that chain() receives do not have a common type. (Rather, that type is 'void'): import std.algorithm; import std.range; import std.traits; class C { } void main() { auto k = C.classinfo; auto m = map!(i => i.classinfo)(k.interfaces); auto b = only(k.base); // Types alias M = typeof(m); alias B = typeof(b); // Element types alias EM = ElementType!M; alias EB = ElementType!B; // Two of chain's constraints are satisfied: static assert(isInputRange!M); static assert(isInputRange!B); // Now it needs to see a CommonType of range elements pragma(msg, EM); // const(void)[]() pragma(msg, EB); // const(void)[]() pragma(msg, CommonType!(EM, EB)); // void // For that reason, the following does not work: // chain(m, b); } AliOn Tue, Jul 04, 2017 at 11:27:25PM +0000, Jean-Louis Leroy via Digitalmars-d-learn wrote:Thanks! However, when I try to use this construct in my real code, I still have a problem: // k is a ClassInfo chain(map!(i => i.classinfo)(k.interfaces), only(k.base)) meth.d(311): Error: template std.range.chain cannot deduce function from argument types !()(MapResult!(__lambda3, Interface[]), OnlyResult!(TypeInfo_Class, 1LU)), candidates are: /usr/include/d/std/range/package.d(795): std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void))I want to create a range that consists of the result of a map() followed by a value, e.g.: int[] x = [ 1, 2, 3]; auto y = map!(x => x * x)(x); auto z = y ~ 99; // how??? I have tried several variations: convert 99 to a dynamic array, to a range, convert range to dynamic array (couldn't even figure that one); to no avail.[...] Try: auto z = chain(y, only(99));
Jul 04 2017
On Wednesday, 5 July 2017 at 00:28:01 UTC, Ali Çehreli wrote:On 07/04/2017 04:57 PM, Jean-Louis Leroy wrote:I suspect that that is the reason, although I checked in several ways that I had ClassInfo elements on both sides. Ok, I'll keep looking tomorrow with a fresh eye...[...]No time to dig deeper but this is because the two ranges that chain() receives do not have a common type. (Rather, that type is 'void'): [...]
Jul 04 2017
On 07/04/2017 05:52 PM, Jean-Louis Leroy wrote:On Wednesday, 5 July 2017 at 00:28:01 UTC, Ali Çehreli wrote:This is related to TypeInfo.init, which unfortunately is *not* the .init property in this case. :( Luckily, it will be fixed in 2.075. This is what object.d has: class TypeInfo { // ... /** * Return default initializer. If the type should be initialized to all * zeros, an array with a null ptr and a length equal to the type size will * be returned. For static arrays, this returns the default initializer for * a single element of the array, use `tsize` to get the correct size. */ abstract const(void)[] initializer() nothrow pure const safe nogc; /// $(RED Removed.) Please use `initializer` instead. disable static const(void)[] init(); // since 2.074 /* Planned for 2.075: Remove init, making way for the init type property, fixing issue 12233. */ } The problem is, ElementType relies on .init, which works on most other type but not TypeInfo: template ElementType(R) { static if (is(typeof(R.init.front.init) T)) alias ElementType = T; else alias ElementType = void; } So, unfortunately, most Phobos range functions cannot be used with TypeInfo as they would invariably touch ElementType. Here is a halfway workaround that uses each() instead of map(): :/ import std.algorithm; class C { } void main() { auto k = C.classinfo; TypeInfo_Class[] arr; each!(i => arr ~= i.classinfo)(k.interfaces); arr ~= k.base; } AliOn 07/04/2017 04:57 PM, Jean-Louis Leroy wrote:I suspect that that is the reason, although I checked in several ways that I had ClassInfo elements on both sides. Ok, I'll keep looking tomorrow with a fresh eye...[...]No time to dig deeper but this is because the two ranges that chain() receives do not have a common type. (Rather, that type is 'void'): [...]
Jul 04 2017
On Wednesday, 5 July 2017 at 01:43:46 UTC, Ali Çehreli wrote:On 07/04/2017 05:52 PM, Jean-Louis Leroy wrote:Aaah, so I was not doing anything wrong ;-) I was trying to factor this code: foreach (i; k.interfaces) { if (i.classinfo in classMap) { v.bases ~= classMap[i.classinfo]; } } if (k.base in classMap) { v.bases ~= classMap[k.base]; } i.e. process the class base along with the interfaces in the same loop. I dwelled on it because my goal with this project is to learn (and evaluate) D. Anyway, I am building my own graph of enriched ClassInfo objects; once that is done, I won't be impacted with the bug anymore. Thanks for the diagnostic... J-LOn Wednesday, 5 July 2017 at 00:28:01 UTC, Ali Çehreli wrote:This is related to TypeInfo.init, which unfortunately is *not* the .init property in this case. :( Luckily, it will be fixed in 2.075. This is what object.d has: [...] So, unfortunately, most Phobos range functions cannot be used with TypeInfo as they would invariably touch ElementType. Here is a halfway workaround that uses each() instead of map(): :/On 07/04/2017 04:57 PM, Jean-Louis Leroy wrote:[...]No time to dig deeper but this is because the two ranges that chain() receives do not have a common type. (Rather, that type is 'void'): [...]
Jul 05 2017
On Tuesday, 4 July 2017 at 23:27:25 UTC, Jean-Louis Leroy wrote:I want to create a range that consists of the result of a map() followed by a value, e.g.: int[] x = [ 1, 2, 3]; auto y = map!(x => x * x)(x); auto z = y ~ 99; // how??? I have tried several variations: convert 99 to a dynamic array, to a range, convert range to dynamic array (couldn't even figure that one); to no avail. Help please...using auto y = x.map!(x => x * x).array; will work.
Jul 04 2017
On Tuesday, July 04, 2017 23:50:57 Nicholas Wilson via Digitalmars-d-learn wrote:On Tuesday, 4 July 2017 at 23:27:25 UTC, Jean-Louis Leroy wrote:Yeah, that will convert the range to a dynamic array, but if you're looking to do is append onto a range, then using chain like H.S. Teoh showed is better. And even if you ultimately want a dynamic array, using chain and then calling array on the result than allocating the array and then appending to it as an array means that you're only going to allocate the array once, whereas if you append to the array, you might end up causing it to be reallocated (though if you're just appending a single element to it it'll have the space unless in std.array.array allocates a dynamic array with exactly the space required for its elements, which I doubt). - Jonathan M DavisI want to create a range that consists of the result of a map() followed by a value, e.g.: int[] x = [ 1, 2, 3]; auto y = map!(x => x * x)(x); auto z = y ~ 99; // how??? I have tried several variations: convert 99 to a dynamic array, to a range, convert range to dynamic array (couldn't even figure that one); to no avail. Help please...using auto y = x.map!(x => x * x).array; will work.
Jul 04 2017