Re: Adding to a global AliasSeq

2023-08-15 Thread Basile B. via Digitalmars-d-learn

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

2023-08-15 Thread repr_man via Digitalmars-d-learn

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

2023-08-15 Thread Joel via Digitalmars-d-learn

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

2023-08-15 Thread FeepingCreature via Digitalmars-d-learn

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

2023-08-15 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2023-08-15 Thread vino via Digitalmars-d-learn

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

2023-08-15 Thread kdevel via Digitalmars-d-learn

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

2023-08-15 Thread ryuukk_ via Digitalmars-d-learn

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

2023-08-15 Thread Joel via Digitalmars-d-learn

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

2023-08-15 Thread bachmeier via Digitalmars-d-learn

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

2023-08-15 Thread IchorDev via Digitalmars-d-learn
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

2023-08-15 Thread FeepingCreature via Digitalmars-d-learn

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

2023-08-15 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

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.