Re: Adding to a global AliasSeq
On Tuesday, 15 August 2023 at 02:30:37 UTC, repr_man wrote: Consider the following template mixin: ```d mixin template Base() { int x(){ return 10; } } ``` It could be used in a variety of structs as follows: ```d struct Child { mixin Base!(); } ``` Now, let's suppose we write a function with a parameter that should only be able to take items that mix in `Base`: ```d auto f(T)(T arg) { return arg.x; } ``` This works because D uses structural subtyping. However, this creates a problem: if we make another struct that looks like it mixes in `Base` and pass it to the function, we could get unexpected results: ```d struct Other { int x = 5; } unittest { import std.stdio; auto c = Child(); auto o = Other(); writeln(f(c)); writeln(f(o)); } ``` The output from running `dub test` is as follows: ``` 10 5 ``` [...] Is there any template-fu of which I am not aware that would make the thing I am trying to do possible? You can add a kind of tag with the mixin, that will allow to to test if the type supplied to `f` is well a Base implementor: ```d mixin template Base() { enum LookImABase = true; int x(){ return 10; } } struct Child { mixin Base!(); } auto f(T)(T arg) if (is(typeof(T.LookImABase))) { return arg.x; } struct Other { int x = 5; } void main(string[] args) { import std.stdio; auto c = Child(); auto o = Other(); writeln(f(c)); // ok writeln(f(o)); // error } ``` This is what is called in D the "design by introspection". There are alternatives way of doing that, notably with UDAs. ```d mixin template Base() { enum Base; @Base int x(){ return 10; } } ``` But the introspection code is more complex (std.traits getUDA, hasUDA) Finally a different approach, with no introspection, is to use a named mixin: ```d mixin template Base() { enum Base; int x(){ return 10; } } struct Child { mixin Base!() base; } auto f(T)(T arg) { return arg.base.x; } struct Other { int x = 5; } void main(string[] args) { import std.stdio; auto c = Child(); auto o = Other(); writeln(f(c)); writeln(f(o)); // error } ``` which works but has the same problem as what lead you to ask your question, for example if it turns out that the supplied argument has unfortunately a `base` member that itself has a `x` member.
Re: Adding to a global AliasSeq
On Tuesday, 15 August 2023 at 07:02:45 UTC, Basile B. wrote: You can add a kind of tag with the mixin, that will allow to to test if the type supplied to `f` is well a Base implementor: Firstly, thank you for your help. This is probably the best solution. Secondly, I feel very stupid for not having come up with this by myself. Would you be willing to explain some of the thought process behind your solution? Are there any key factors that I should look for in future template-related problems? Or, if it just comes from experience and seeing this sort of thing repeatedly, that's fair, too. Thanks, once again!
toLower
How come toLower works in the sort quotes, but not in the map? ```d void main() { import std; "EzraTezla" .to!(char[]) .byCodeUnit .sort!"a.toLower c.toLower) .writeln; } ``` onlineapp.d(60): Error: `toLower` matches conflicting symbols: /dlang/dmd/linux/bin64/../../src/phobos/std/uni/package.d(9819): function `std.uni.toLower` /dlang/dmd/linux/bin64/../../src/phobos/std/ascii.d(637): function `std.ascii.toLower!char.toLower` /dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(479):instantiated from here: `MapResult!(__lambda4, SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))` onlineapp.d(60):instantiated from here: `map!(SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))`
Re: toLower
On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote: How come toLower works in the sort quotes, but not in the map? ```d void main() { import std; "EzraTezla" .to!(char[]) .byCodeUnit .sort!"a.toLower c.toLower) .writeln; } ``` When you pass a string to a lambda, it's evaluated in `std.functional.unaryFun`/`binaryFun`. At that point, these modules are imported for use in string expressions: ``` import std.algorithm, std.conv, std.exception, std.math, std.range, std.string; import std.meta, std.traits, std.typecons; ``` And `std.string` itself publically imports: ``` public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace; ``` But does *not* import `std.ascii`! So there's no ambiguity inside the `sort` string expression between the two `toLower` functions..
Re: AA vs __gshared
On 8/12/23 5:55 AM, IchorDev wrote: On Thursday, 10 August 2023 at 15:20:28 UTC, Steven Schveighoffer wrote: That shouldn't matter. Well, it does here. The AA is mutated during the loop, so perhaps this is an optimisation quirk where it works with `for` but segfaults in `foreach`? I've pretty thoroughly abused the `for` version and I haven't gotten it to segfault yet. oh yeah. That is not allowed. Any mutation of the AA during iteration can invalidate existing foreach or ranges over the AA. Basically, a rehash can cause the buckets to jumble up, and in that case, the "current index" can be changed to point at a null bucket. More here: https://dlang.org/spec/statement.html#foreach_restrictions In fact, that statement is way too broad. Invalidation of iteration should be based on the type's requirements. We really should put a note in the AA spec page. I also highly recommend using `emplace` to handle all the sticky issues with lifetime/construction. Have not run into the aforementioned sticky issues yet, but I can't even find `emplace`'s docs anywhere now. https://dlang.org/phobos/core_lifetime.html#.emplace I recall it being incompatible with classes that have @nogc/nothrow constructors though, which made it pretty useless to me, and it wouldn't work with BetterC, which was a requirement for the allocation wrapper I was writing at the time. It probably won't work with betterC, but that's probably just because of linker errors. Any attribute requirements would be inferred based on the attributes of your constructor, because emplace is a template. -Steve
Finding duplicate elements
Hi All, Request your help in finding duplicate element without sorting as per the below example ``` Example: string[] args = [" test3", "test2 ", " test1 ", " test1 ", " "]; Output Required: If duplicate element found then print "Duplicate element found: " else print ["test3", "test2", "test1"]; ``` From, Vino.B
Re: Finding duplicate elements
On Tuesday, 15 August 2023 at 17:59:27 UTC, vino wrote: Request your help in finding duplicate element without sorting as per the below example ```d module remove_duplicates; import std.stdio; import std.format : format; import std.string : strip; int main (string [] args) { bool [string] found; string [] result; foreach (s; args [1..$]) { auto t = s.strip; if (t == "") continue; if (t in found) stderr.writefln!"Duplicate element found: <%s>" ("element name"); else { found [t] = true; result ~= t; } } result.writeln; return 0; } ``` ``` $ ./remove-duplicates " test3" "test2 " " test1 " " test1 " " " Duplicate element found: ["test3", "test2", "test1"] ```
Re: toLower
On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote: How come toLower works in the sort quotes, but not in the map? ```d void main() { import std; "EzraTezla" .to!(char[]) .byCodeUnit .sort!"a.toLower c.toLower) .writeln; } ``` onlineapp.d(60): Error: `toLower` matches conflicting symbols: /dlang/dmd/linux/bin64/../../src/phobos/std/uni/package.d(9819): function `std.uni.toLower` /dlang/dmd/linux/bin64/../../src/phobos/std/ascii.d(637): function `std.ascii.toLower!char.toLower` /dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(479):instantiated from here: `MapResult!(__lambda4, SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))` onlineapp.d(60):instantiated from here: `map!(SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))` This error message is unreadable, maybe an issue should be opened about it, so it could be improved, took me a while to understand, or rather "decipher", what it says..
Re: toLower
On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote: On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote: [...] When you pass a string to a lambda, it's evaluated in `std.functional.unaryFun`/`binaryFun`. At that point, these modules are imported for use in string expressions: ``` import std.algorithm, std.conv, std.exception, std.math, std.range, std.string; import std.meta, std.traits, std.typecons; ``` And `std.string` itself publically imports: ``` public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace; ``` But does *not* import `std.ascii`! So there's no ambiguity inside the `sort` string expression between the two `toLower` functions.. How do I get it to work? I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower;
Re: toLower
On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote: On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote: On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote: [...] When you pass a string to a lambda, it's evaluated in `std.functional.unaryFun`/`binaryFun`. At that point, these modules are imported for use in string expressions: ``` import std.algorithm, std.conv, std.exception, std.math, std.range, std.string; import std.meta, std.traits, std.typecons; ``` And `std.string` itself publically imports: ``` public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace; ``` But does *not* import `std.ascii`! So there's no ambiguity inside the `sort` string expression between the two `toLower` functions.. How do I get it to work? I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower; Changing your map line to ``` .map!(c => std.uni.toLower(c)) ``` works for me.
Re: AA vs __gshared
On Tuesday, 15 August 2023 at 17:36:13 UTC, Steven Schveighoffer wrote: On 8/12/23 5:55 AM, IchorDev wrote: On Thursday, 10 August 2023 at 15:20:28 UTC, Steven Schveighoffer wrote: That shouldn't matter. Well, it does here. The AA is mutated during the loop, so perhaps this is an optimisation quirk where it works with `for` but segfaults in `foreach`? I've pretty thoroughly abused the `for` version and I haven't gotten it to segfault yet. oh yeah. That is not allowed. Any mutation of the AA during iteration can invalidate existing foreach or ranges over the AA. And yet this apparently doesn’t apply to an equivalent `for` somehow. Perhaps `foreach` shouldn’t have this arbitrary problem in the first place… In fact, that statement is way too broad. Invalidation of iteration should be based on the type's requirements. We really should put a note in the AA spec page. Probably yeah. https://dlang.org/phobos/core_lifetime.html#.emplace Any attribute requirements would be inferred based on the attributes of your constructor, because emplace is a template. -Steve Well the docs don’t say that at all, and the code is an unreadable mess. I dunno how anymore is meant to figure that out?
Re: toLower
On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote: On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote: But does *not* import `std.ascii`! So there's no ambiguity inside the `sort` string expression between the two `toLower` functions.. How do I get it to work? I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower; To elaborate more, `toLower` doesn't work because function-scope aliases are not considered for UFCS. ``` alias toLower = std.ascii.toLower; ... // So this does actually work: .map!toLower // but this does not, because it looks for a UFCS-capable symbol .map!(c => c.toLower) // but this does again .map!(c => toLower(c)) ```
Re: Finding duplicate elements
On Tuesday, 15 August 2023 at 17:59:27 UTC, vino wrote: Hi All, Request your help in finding duplicate element without sorting as per the below example ``` Example: string[] args = [" test3", "test2 ", " test1 ", " test1 ", " "]; Output Required: If duplicate element found then print "Duplicate element found: " else print ["test3", "test2", "test1"]; ``` From, Vino.B Another approach would be using a rbtree as container at the first place.