Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 10 May 2024 at 01:00:09 UTC, Andy Valencia wrote:

On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote:
Yes. The reason for this is that it avoids having to 
essentially do the same check twice. If `in` returned a bool 
instead of a pointer, after checking for whether the element 
exists (which requires searching for the element in the 
associative array), you'd then have to actually *get* it from 
the array, which would require searching again. Returning a 
pointer to the element if it exists (or `null` if it doesn't) 
cuts this down to 1 operation.


Looking at Programming in D section 28.5, I'm guessing that 
pointer versus null is treated as the appropriate boolean value 
when consumed by an "if" test.  So that example is getting a 
pointer to a string, or null, but the example looks exactly as 
the same as if it had directly gotten a bool.


Yes, we say that a type has "truthiness" if it can be used in a 
condition (`while`, `if`, `assert`, etc).


For a pointer, `null` is considered "false", whereas any other 
value is considered "true". So you can use statements like 
`if(key in aa)` to test for membership. A very nice idiom is to 
check if a key is in an associative array, and if so, use the 
value that it maps to:


```d
if(auto v = key in aa) {
   // use *v as the value here
}
```

You can change your code to `return (e in this.members) !is null;`

-Steve


Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Andy Valencia via Digitalmars-d-learn

On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote:
Yes. The reason for this is that it avoids having to 
essentially do the same check twice. If `in` returned a bool 
instead of a pointer, after checking for whether the element 
exists (which requires searching for the element in the 
associative array), you'd then have to actually *get* it from 
the array, which would require searching again. Returning a 
pointer to the element if it exists (or `null` if it doesn't) 
cuts this down to 1 operation.


Looking at Programming in D section 28.5, I'm guessing that 
pointer versus null is treated as the appropriate boolean value 
when consumed by an "if" test.  So that example is getting a 
pointer to a string, or null, but the example looks exactly as 
the same as if it had directly gotten a bool.


Thank you!
Andy



Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Meta via Digitalmars-d-learn

On Friday, 10 May 2024 at 00:18:16 UTC, Andy Valencia wrote:
tst7.d(6): Error: cannot implicitly convert expression `e in 
this.members` of type `bool*` to `bool`
tst7.d(15): Error: template instance `tst7.Foo!uint` error 
instantiating


I'm getting this for this bit of source (trimmed from the 
bigger code).  I switched to this.members.get(e, false) and 
that works fine, but I'm still curious:


struct Foo(T) {
bool[T] members;

bool
has(T e) {
return (e in this.members);
}
}

void
main()
{
import std.stdio : writeln;

auto t = Foo!uint();
writeln(t.has(123));
}


Yes. The reason for this is that it avoids having to essentially 
do the same check twice. If `in` returned a bool instead of a 
pointer, after checking for whether the element exists (which 
requires searching for the element in the associative array), 
you'd then have to actually *get* it from the array, which would 
require searching again. Returning a pointer to the element if it 
exists (or `null` if it doesn't) cuts this down to 1 operation.


"in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Andy Valencia via Digitalmars-d-learn
tst7.d(6): Error: cannot implicitly convert expression `e in 
this.members` of type `bool*` to `bool`
tst7.d(15): Error: template instance `tst7.Foo!uint` error 
instantiating


I'm getting this for this bit of source (trimmed from the bigger 
code).  I switched to this.members.get(e, false) and that works 
fine, but I'm still curious:


struct Foo(T) {
bool[T] members;

bool
has(T e) {
return (e in this.members);
}
}

void
main()
{
import std.stdio : writeln;

auto t = Foo!uint();
writeln(t.has(123));
}


Re: Why is Phobos `Flag` so overthought ?

2024-05-09 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 8 May 2024 at 10:24:07 UTC, Nick Treleaven wrote:
Named arguments are optional, so I don't see how they could 
make Flag redundant.


Actually, an external tool could detect when a bool is passed as 
an argument to a function and warn when not done with a named 
argument. This would free library APIs from having to use Flag 
when some users don't care about it. The cost would come in a bit 
more build system complexity/build time, which might mean a lot 
less enforcement due to inertia. Though maybe a reasonable 
trade-off.


Re: Why is Phobos `Flag` so overthought ?

2024-05-09 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 9 May 2024 at 13:40:56 UTC, cc wrote:
It's pointless mandatory verbosity.  StopWatch ctor only takes 
one boolean argument.  It doesn't *need* to specify what it 
relates to.  You either already know, or you have to look it up 
anyway.  Flags made sense when you might get the order of 
multiple bools confused, but if there's only one, *or* if you 
can use named arguments to avoid ambiguity,


So you have justified Flag.

there's no point in demanding every parameter be a unique type. 
 It's easy to remember I can pass a bool to a StopWatch to 
autostart it.


But perhaps true means manual start? Remembering can also be used 
to justify dynamic typing outside of hot loops, I'd rather not 
rely on remembering with a big team of programmers working on a 
project.


It's less easy to remember that a specific unique type needs to 
be used, and remembering whether the name/casing of that type 
was Start, StartNow, StartAuto, Autostart, AutoStart, 
autostart, autoStart, etc.


So just pass it true, and run the compiler. The compiler will 
tell you what the correct type is.


 We have a tool in our box already called `true` and that 
solves the problem.  If we had to type out the full name of 
every argument passed to every function ever written we may as 
well just adopt ObjC Cocoa style and call it 
StopWatchWithAutoStartBool().


Strawman.


Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?

2024-05-09 Thread evilrat via Digitalmars-d-learn

On Thursday, 9 May 2024 at 00:39:49 UTC, Liam McGillivray wrote:


What's a good way I can achieve what I'm trying to do, using 
either reference counting or a garbage-collected object?


There is libraries like `automem`[1] that implements refcounting 
and more.
Without showing your code for ref counted struct we can't help 
you.


As for weak references, maybe you could "trick" the GC by using 
the fact that simple types are not scanned, i.e. do something 
like this but I have no idea if this is going to work at all, 
alternatively you can also try using `ubyte[size_t.sizeof]`.


Keep in mind that classes is already references so you don't need 
that extra pointer for classes, can be versioned with template 
specialization.


```d
struct WeakRef(T) {
private size_t _handle; // same size as a pointer

this(T* ptr) {
_handle = cast(size_t) ptr;
}

T* getRef() {
return cast(T*) _handle;
}

// do the rest ...
}
```

[1] https://code.dlang.org/packages/automem


Re: Why is Phobos `Flag` so overthought ?

2024-05-09 Thread cc via Digitalmars-d-learn

On Wednesday, 8 May 2024 at 10:24:07 UTC, Nick Treleaven wrote:

On Wednesday, 8 May 2024 at 04:27:13 UTC, cc wrote:
It doesn't allow a simple boolean to be used as an argument, 
or any other Flag as they are different instantiations of a 
template rather than equivalent aliases.
It is however awful, cumbersome, annoying design and needs to 
be completely phased out now that we have named arguments.


Flag enforces that the argument says what it relates to. `true` 
does not say what it relates to. Named arguments are optional, 
so I don't see how they could make Flag redundant.


It's pointless mandatory verbosity.  StopWatch ctor only takes 
one boolean argument.  It doesn't *need* to specify what it 
relates to.  You either already know, or you have to look it up 
anyway.  Flags made sense when you might get the order of 
multiple bools confused, but if there's only one, *or* if you can 
use named arguments to avoid ambiguity, there's no point in 
demanding every parameter be a unique type.  It's easy to 
remember I can pass a bool to a StopWatch to autostart it.  It's 
less easy to remember that a specific unique type needs to be 
used, and remembering whether the name/casing of that type was 
Start, StartNow, StartAuto, Autostart, AutoStart, autostart, 
autoStart, etc.  We have a tool in our box already called `true` 
and that solves the problem.  If we had to type out the full name 
of every argument passed to every function ever written we may as 
well just adopt ObjC Cocoa style and call it 
StopWatchWithAutoStartBool().


moving from classical lex/yacc to pegged parser

2024-05-09 Thread Dmitry Ponyatov via Digitalmars-d-learn
Using lex/yacc I can do a more or less complex things in .yacc 
semantic actions, such complex as bytecode compilation or real 
CPU assembly.


Playing with `pegged`, I can't figure out how to move from 
`ParseTree` to such like semantic actions. I even can't parse 
numbers from strings in lexer-like rules because it looks like 
every rule runs on any token parse, or sumething like this.


Also, I use attribute object trees resemble attribute grammar 
both for parsing and internal code representation:


```C++
class Object {
  string   value; // or `int value` and `float value` 
for numbers

  map attr;
  vector  nested;
}
```

And I also can't figure out how to inherit `ParseTree` with all 
my script language objects to get AST right from pegged parser. 
Should I use some superloop with lot of matches to process parsed 
`pt` tree into something I need myself, to drop all unneeded 
parsing meta info and get clean semantic AST?