Re: Any way to automatically convert structs on return?

2024-08-01 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 1 August 2024 at 08:46:00 UTC, IchorDev wrote:
P.S. You might want to put `value = void`, otherwise it’ll 
always be default-constructed.


Doing `= void` can violate the assumptions of a destructor of T. 
Nullable uses a union to store T, so it can decide when to call 
the destructor.


Re: Prevent self-comparison without taking the address

2024-07-25 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 25 July 2024 at 15:06:35 UTC, IchorDev wrote:
I think your function most likely has a safe interface, so it 
can be marked as `@trusted` as-per [the 
spec](https://dlang.org/spec/function.html#safe-interfaces).


Just to mention that with -dip1000, taking the address of 
variables is allowed, so the function would be @safe.


Re: Array concatenation & optimisation

2024-07-22 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 21 July 2024 at 10:33:38 UTC, Nick Treleaven wrote:

On Sunday, 21 July 2024 at 05:43:32 UTC, IchorDev wrote:
Does this mean that array literals are *always* separately 
allocated first, or is this usually optimised out?


My understanding is that they do not allocate if used to 
initialize or assign a static array. That includes passing an 
array literal as an argument to a static array function 
parameter.


A scope slice can also be initialized from an array literal in 
@nogc code:

https://dlang.org/changelog/2.102.0.html#dmd.scope-array-on-stack


Another (related) case that doesn't heap allocate is when passing 
a literal as a scope parameter:


```d
void main() @nogc {
f([1,2]);
}

void f(scope int[]) @nogc;
```

I will look at adding these cases to the spec.


Re: Array concatenation & optimisation

2024-07-21 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 21 July 2024 at 10:33:38 UTC, Nick Treleaven wrote:
For instance, will this example *always* allocate a new 
dynamic array for the array literal, and then append it to the 
existing one, even in optimised builds?

```d
void append(ref int[] a){
a ~= [5, 4, 9];
}
```


If there is enough spare capacity in a's allocation, no 
allocation will occur.


Sorry, I see what you mean. I've compared the -vasm output 
(without -O) for that function and this one:


```d
void append(ref int[] a){
enum e = [5, 4, 9];
a ~= e;
}
```
The ASM output is the same. If you use runtime value elements I'm 
not sure but I think there's still no heap allocation.


I'm not good at reading ASM though.


Re: Tuple deconstruction in Phobos

2024-07-21 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 21 July 2024 at 04:05:52 UTC, IchorDev wrote:

On Saturday, 20 July 2024 at 20:48:29 UTC, Nick Treleaven wrote:

Instead of the `tie` assignment, you can just do:
```d
import std.meta;
AliasSeq!(y, x) = tupRetFn().expand;
```


And here I was trying to use comma expressions for this like a 
buffoon! Of course they didn't work, but I'm pleasantly 
surprised that using a sequence does.


I think The lvalue sequence docs in template.dd were only updated 
in the last year to mention sequence assignment.


I should really PR `std.typecons` to add a couple of examples 
of this, because I think a lot of people will have overlooked 
it.


Good idea.



Re: Array concatenation & optimisation

2024-07-21 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 21 July 2024 at 05:43:32 UTC, IchorDev wrote:
Obviously when writing optimised code it is desirable to reduce 
heap allocation frequency. With that in mind, I'm used to being 
told by the compiler that I can't do this in `@nogc` code:

```d
void assign(ref int[4] a) @nogc{
	a[] = [1,3,6,9]; //Error: array literal in `@nogc` function 
`assign` may cause a GC allocation

}
```


Just to mention that if you assign to the static array it works: 
`a = [1,3,6,9];`.



'may cause' a GC allocation


Does this mean that array literals are *always* separately 
allocated first, or is this usually optimised out?


My understanding is that they do not allocate if used to 
initialize or assign a static array. That includes passing an 
array literal as an argument to a static array function parameter.


A scope slice can also be initialized from an array literal in 
@nogc code:

https://dlang.org/changelog/2.102.0.html#dmd.scope-array-on-stack

But assigning a literal to a scope slice is not allowed in @nogc 
code.


For instance, will this example *always* allocate a new dynamic 
array for the array literal, and then append it to the existing 
one, even in optimised builds?

```d
void append(ref int[] a){
a ~= [5, 4, 9];
}
```


If there is enough spare capacity in a's allocation, no 
allocation will occur.


Obviously for a long array literal, the benefit of knowing its 
length upfront (and the readability) would probably outweigh 
the allocation; but for small array literals, is splitting them 
into separate concatenations going to yield faster code, or 
will I waste my time and screen space?


Note that concatenation always allocates:

Concatenation always creates a copy of its operands, even if 
one of the operands is a 0 length array


https://dlang.org/spec/arrays.html#array-concatenation

P.S. I am mostly addressing LDC2 & GDC's output, since I am 
aware that DMD's optimisations are usually minimal.


While people may say that on the forum, dmd's optimizer does 
actually do data flow analysis:

https://forum.dlang.org/post/uqhgoi$31a7$1...@digitalmars.com


Re: Tuple deconstruction in Phobos

2024-07-20 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 20 July 2024 at 14:02:21 UTC, IchorDev wrote:
Why does Phobos not provide a method to easily deconstruct 
tuples? Here's a trivial implementation:

...

tie!(y, x) = tupRetFn().expand;
writeln(x,", ",y);
}
```
Not having this is like if Phobos didn't have `AliasSeq`. Yes 
you can make your own, but it's wasteful boilerplate.


Instead of the `tie` assignment, you can just do:
```d
import std.meta;
AliasSeq!(y, x) = tupRetFn().expand;
```


Re: need help to check symbol is static variable or not

2024-07-15 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 15 July 2024 at 06:44:12 UTC, Dakota wrote:

```d
struct type_s
{

union {
struct
{
int a;
int b;
} c;
};
};
```

`type c` will return false with `enum isStatic(alias V) = 
__traits(compiles, { enum v = V; });`


I put `type_s` in a file anonstruct.c, then:
```d
import anonstruct;

pragma(msg, isStatic!(type_s.c));
```
That outputs `false`, because the symbol is not a compile-time 
value. Is that what you meant?


Re: need help to check symbol is static variable or not

2024-07-01 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 1 July 2024 at 07:32:30 UTC, Dakota wrote:

this code give error:

```d
static if(  !__traits(compiles, mixin("enum v = V;")) ) {
   enum v = V;
}

```


__traits(compiles, ...) can't check if a declaration is valid 
directly. You have to wrap it in a function literal expression:

```d
enum isStatic(alias V) = __traits(compiles, { enum v = V; });

extern const float NotWorkVar;
const float Works = 2;

pragma(msg, isStatic!NotWorkVar); // false
pragma(msg, isStatic!Works); // true
```


Re: Default struct constructors if a struct member is a union

2024-06-30 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote:

S foo0 = S(TypeEnum.Integer32, S(20));  //Ugly, but works
S foo1 = S(TypeEnum.Integer64, S(20L)); //Error: cannot


Did you mean `U(20)`? The 20 applies to the first field of the 
union, i32. `U(20L)` also works and (I think) it does the same 
because of VRP.


My question is can I initialize structs like these in one line 
without relying on a second line? My usecase scenario doesn't 
really allow constructors for the struct, since it's a binding 
to an external library via C API.


You can use a field initializer:
```d
enum TypeEnum { Integer32, Integer64 }

union U {
int i32;
long i64;
float f32;
double f64;
}

struct S {
TypeEnum type;
U data;
}

S foo0 = S(TypeEnum.Integer32, U(20)); // init i32
S foo1 = S(TypeEnum.Integer64, U(f32: 0.5F));

// struct initializer syntax
S foo2 = {TypeEnum.Integer32, {20}};
S foo3 = {TypeEnum.Integer64, {f32: 0.5F}}; // init f32

void main()
{
assert(foo0.data.i32 == 20);
assert(foo3.data.f32 == 0.5F);
}
```


Re: Why `foo.x.saa.aa` and `foo.y.saa.aa` is the same? `shared_AA.saa` should still be instance variable, not class variable, right?

2024-06-25 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 25 June 2024 at 02:16:25 UTC, mw wrote:
Why `foo.x.saa.aa` and `foo.y.saa.aa` is the same? (and of 
course print out the same contents).


`shared_AA.saa` should still be instance variable, not class 
variable, right?


`saa` is an instance variable, but both `foo.x.saa` and 
`foo.y.saa` are initialized to the same instance of 
`shared_AA_class`. I think in the next edition of D we can forbid 
tail mutable initializers.


BTW there's also another issue that the initializer is not TLS - 
that could probably be fixed (also in an edition) to use TLS.


https://forum.dlang.org/post/sexmkjnbtxvsvodca...@forum.dlang.org


Re: How to generate a random number from system clock as seed

2024-06-08 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 8 June 2024 at 16:09:04 UTC, monkyyy wrote:
rng is an optional parameter, `uniform(0,100).writeln;` alone 
works; the docs not telling you that is really bad


They do tell you:

urng 	(optional) random number generator to use; if not 
specified, defaults to rndGen


That overload is used in the 2nd example.

https://dlang.org/phobos/std_random.html#.uniform



Re: Unintentional sharing?

2024-06-06 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 6 June 2024 at 17:49:39 UTC, Andy Valencia wrote:
I was using instance initialization which allocated a new 
object.  My intention was this initialization would happen 
per-instance, but all instances appear to share the same 
sub-object?  That is, f1.b and f2.b appear to point to a single 
object?  Obviously I moved the new into the initializer code, 
but I hadn't appreciated how initial instance values were 
calculated once.  Interestingly, this makes it similar to how 
Python calculates default argument values for functions.


class Bar {
int z = 3;
}

class Foo {
auto b = new Bar();
}

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

auto f1 = new Foo(), f2 = new Foo();
f1.b.z = 0;
writeln(f2.b.z);
}


This is a long standing issue:
https://issues.dlang.org/show_bug.cgi?id=2947

I think with the next edition we can disallow (tail) mutable 
initializers for fields (and TLS globals too).


Re: How to pass in reference a fixed array in parameter

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

On Wednesday, 5 June 2024 at 09:24:23 UTC, evilrat wrote:
for simple cases like this it might work, but 2d array is not 
even contiguous,


A 2D static array is contiguous:
https://dlang.org/spec/arrays.html#rectangular-arrays

D static arrays, while using the same syntax, are implemented 
as a fixed rectangular layout in a contiguous block of memory


Re: How to pass in reference a fixed array in parameter

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

On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote:

   foreach (i, row; maze)
   slices[i] = row;


Sorry that assignment was wrong (edited at last minute). Fixed:

```d
import std.stdio;
alias s_cell = int;

void main()
{  writeln("Maze generation demo");

   s_cell [5][5] maze;
   int n;
   foreach (i, row; maze)
foreach (j, col; row)
maze[i][j] = n++;

   s_cell[][5] slices;
   foreach (i, _; maze)
   slices[i] = maze[i];

   print_maze (slices);
}

void print_maze ( s_cell [][] maze )
{
foreach (a; maze)
a.writeln();
}
```


Re: How to pass in reference a fixed array in parameter

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

On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote:

//~ void print_maze ( s_cell [][] maze... )


I meant to delete that line!


Re: How to pass in reference a fixed array in parameter

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

On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote:

~~~
void main()
{  writeln("Maze generation demo");

   s_cell [5][5] maze;
   print_maze (maze);

}

void print_maze ( s_cell [][] maze )
{
}
~~~


This is how to do it without GC allocations (I have used `int` 
instead for demo purposes):


```d
import std.stdio;
alias s_cell = int;

void main()
{  writeln("Maze generation demo");

   s_cell [5][5] maze = [0, 1, 2, 3, 4];
   s_cell[][5] slices; // static array of 5 slices
   foreach (i, row; maze)
   slices[i] = row;

   print_maze (slices);
}

//~ void print_maze ( s_cell [][] maze... )
void print_maze ( s_cell [][] maze )
{
foreach (a; maze)
a.writeln();
}
```


Re: How to pass in reference a fixed array in parameter

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

On Wednesday, 5 June 2024 at 06:22:34 UTC, Eric P626 wrote:
Now according to the book, it's possible to assign a slice from 
a fixed array. This code will compile:


~~~
int[12] monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 
30, 31 ];

int[] a_slice = monthDays;
~~~


The element types are both int, so the compiler can slice the 
static array. As if you had written `a_slice = monthDays[];`.


How come the assignment does not work when passing a parameter. 
I tried the following and it failed:


~~~
s_cell [5][5] maze;


The element type is s_cell[5].


s_cell [][] sliced_maze = maze;


The element type of sliced_maze is s_cell[], so the element types 
are incompatible.



~~~
void print_maze ( ref s_cell maze )
void print_maze ( ref s_cell [][] maze )
~~~

From what I found, arrays passed in parameters are always 
passed by reference. So the ref keyword seems pointless.


You don't need `ref` to be able to read the array length and 
elements.
However, if you want to modify the array length, and have it 
affect the caller's dynamic array, you need `ref`.




---

The only solution left is to use pointers. But even this does 
not seems to work as in C. I created a function with different 
pointer signature and they all fails.


Normally in C, this would have worked:

~~~
s_cell [5][5] maze;
create_maze();


Pass `[0][0]` instead.


~~~
Error: function `mprmaze.create_maze(s_cell[][]* maze)` is not 
callable using argument types `(s_cell[5][5]*)`
cannot pass argument `& maze` of type `s_cell[5][5]*` to 
parameter `s_cell[][]* maze`

~~~


s_cell[5][5] cannot implicitly convert to s_cell[][].

Now I think it expect a 2D array of pointers instead of a 
pointer on a 2D array.


It's also not clear if there is a difference between those 2 
notations:


~~~

maze.ptr
~~~


 is a pointer to s_cell[5][5].
maze.ptr is a pointer to s_cell[5]. `.ptr` means a pointer to the 
first element of the array.




Re: bool passed by ref, safe or not ?

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

On Wednesday, 5 June 2024 at 09:09:40 UTC, Kagamin wrote:

On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote:

The only safe values for a `bool` are 0 (false) and 1 (true).


AFAIK that was fixed and now full 8-bit range is safe.


`cast(bool) someByte` is fine - that doesn't reinterpret the bit 
representation.


The problem is certain values such as `0x2` for the byte 
representation can cause the boolean to be both true and false:

https://issues.dlang.org/show_bug.cgi?id=20148#c3

Void initialization of bool and bool union fields are now 
deprecated in @safe functions as of 2.109. There is a remaining 
case of casting an array to bool[], which I am working on 
disallowing in @safe.


Re: What prevents ImportC from using .h directly?

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

On Sunday, 12 May 2024 at 21:34:30 UTC, Chris Piker wrote:
So, why does ImportC need *.c files exclusively?  I'm sure it 
solves a problem, but I don't know what that problem is.


Support for headers has been worked on, but had to be reverted:
https://issues.dlang.org/show_bug.cgi?id=23479


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

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

On Friday, 10 May 2024 at 15:23:39 UTC, Andy Valencia wrote:
On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer 
wrote:
Yes, we say that a type has "truthiness" if it can be used in 
a condition (`while`, `if`, `assert`, etc).


So if I may ask for one more small clarification... WRT 
"truthiness", I've observed that empty arrays are treated as 
false, non-empty as true.


Arrays evaluate to true in boolean conditions if their `.ptr` 
field is non-null. This is bug-prone and I hope we can remove 
this in the next edition.


However, although I thought a string was basically an immutable 
array of characters, "" is treated as true, not false?


A string literal's `.ptr` field is always non-null, because it is 
null-terminated.


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: Why is Phobos `Flag` so overthought ?

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

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.


Re: How can I put the current value of a variable into a delegate?

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

On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote:

Here's a line that caused a bug that took me awhile to find:
```
foreach(card; unitCards) card.submitted = delegate() => 
selectUnit(card.unit);

```


I think you can do:
```d
import std.algorithm.iteration : each;
unitCards.each!(c => c.submitted = () => selectUnit(c.unit));
```



Re: How can I put the current value of a variable into a delegate?

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

On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote:
This is because the delegate assignment causes the local `card` 
variable to remain alive. The delegate that's assigned is 
linked to this variable itself, not the value at the time that 
the delegate is assigned.


This is https://issues.dlang.org/show_bug.cgi?id=23136. Perhaps 
it can be fixed in the next edition.


Is there a way I can dereference a variable when placing it in 
a delegate, so that it's current value is used, rather than the 
variable itself?


I think you would need to make an array before the loop, assign 
to an indexed element and use that in the delegate.


Re: Turning fixed sized array into tuple

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

On Saturday, 4 May 2024 at 16:58:00 UTC, Dmitry Olshansky wrote:

So I have a function:

```d
size_t awaitAny(T...)(T args) { ... }
```

And I have:
``d
Event*[4] events;
``

How do I pass all 4 of events to awaitAny as tuple of arguments?


Use `awaitAny(events.tupleof)`?
https://dlang.org/spec/arrays.html#array-properties


Re: Phobos function to remove all occurances from dynamic array?

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

On Wednesday, 1 May 2024 at 01:09:33 UTC, Liam McGillivray wrote:
I get compiler errors when using it on other array types. I've 
tried using it to replace occurrences of a certain object in an 
array with [] in order to remove all occurrences, but it's not 
allowed.


Can you post a code example?


Re: Challenge Tuples

2024-04-27 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 27 April 2024 at 15:32:40 UTC, Nick Treleaven wrote:

On Saturday, 27 April 2024 at 11:55:58 UTC, Basile B. wrote:

foreach const e in u do
if echo(is, e, T) do
result += e;



static if (is(typeof(e) == int))
r += e;


Actually I would write that:
```d
R r;
foreach (e; v)
{
static if (is(typeof(e) : R))
```


Re: Challenge Tuples

2024-04-27 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 27 April 2024 at 11:55:58 UTC, Basile B. wrote:

Here's [STYX](https://gitlab.com/styx-lang/styx) solution:


function sum[T,U](U u): u32


I think you meant `: T`.


{
var T result;
foreach const e in u do
if echo(is, e, T) do
result += e;
else do
result += sum![T](e);
return result;
}

function main(): s32
{
assert((1, 2, 3, [1, 3], 5).sum![u32]() == 15);
return 0;
}


Mostly equivalent D:
```d
R sum(R = long, T)(T v)
{
R r;
foreach (e; v)
{
static if (is(typeof(e) == int))
r += e;
else
r += sum!R(e);
}
return r;
}

void main()
{
import std;
assert(tuple(1, 2, 3, [1, 3], 5).sum == 15);
}
```


Re: std.traits.ParameterIdentifierTuple problem

2024-04-01 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 31 March 2024 at 23:05:44 UTC, Carl Sturtivant wrote:

Yes, it's not possible to instantiate a function type.


But with extern it seems the semantics is fine as a function is 
not being instantiated. It is merely associating a name with a 
type: in what sense is this instantiation in any reasonable way?


Yes there is no instantiation for extern. But what would be the 
use of allowing an extern function type instance, when there's no 
way to instantiate it?


Re: std.traits.ParameterIdentifierTuple problem

2024-03-31 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 30 March 2024 at 22:37:53 UTC, Carl Sturtivant wrote:
I'm inclined to a view that keeps more "it just works" options 
open. Regard the parameter names as a part of the type (which I 
am very grateful for them being currently) and just regard part 
of the definition of "type equality" as being to ignore 
parameter names when comparing types.


With this viewpoint, ParameterIdentifierTuple should be 
repaired to work with function types just as it works with 
functions, and the current behavior is a bug.


Maybe, but one of its unittests specifically tests that a 
function pointer has no parameter identifiers:

```d
// might be changed in the future?
void function(int num, string name) fp;
static assert([ParameterIdentifierTuple!fp] == ["", ""]);
```
And changing in the future got quite a bit of push back in that 
PR link.


This is because `fp` is declared using a function pointer type, 
and the author of the test did not think function pointer types 
should include identifiers. So it seems logical that 
ParameterIdentifierTuple should not give identifiers for a 
function type either.


If a function type does include identifiers, then would two 
function types with the same argument types but different 
identifiers compare equal using `is`?



Incidentally, I tried
```D
extern typeof(foo) func;
```
to say that func was an actual function (`extern` so defined 
elsewhere) whose type was the type of the function `int foo(int 
num, string name, int);` so I can then use 
`ParameterIdentifierTuple` on a function, not a type,


Nice try!

but the compiler said `bug1.d(5): Error: variable ``bug1.func`` 
cannot be declared to be a function`. Seems unreasonable given 
the implied semantics.


Yes, it's not possible to instantiate a function type.



Re: std.traits.ParameterIdentifierTuple problem

2024-03-30 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 30 March 2024 at 21:45:34 UTC, Nick Treleaven wrote:
On Saturday, 30 March 2024 at 21:25:45 UTC, Carl Sturtivant 
wrote:
OK, so how can I get them? Am I forced to take that string and 
parse it with CTFE?


Lookup the source of ParameterIdentifierTuple and change 
`FunctionTypeOf!func` to just `func` inside the first `static 
if`.


Sorry, that actually doesn't work.


Re: std.traits.ParameterIdentifierTuple problem

2024-03-30 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 30 March 2024 at 21:25:45 UTC, Carl Sturtivant wrote:
OK, so how can I get them? Am I forced to take that string and 
parse it with CTFE?


Lookup the source of ParameterIdentifierTuple and change 
`FunctionTypeOf!func` to just `func` inside the first `static if`.


Re: std.traits.ParameterIdentifierTuple problem

2024-03-30 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 30 March 2024 at 19:23:07 UTC, Carl Sturtivant wrote:

$ dmd -c bug1.d
int(int num, string name, int)
["", "", ""]
bug1.d(9): Error: static assert:  "wrong!"
```
Please explain. How do I get the names of the identifiers out 
of a parameter list at compile time reliably?


Although `.stringof` on a function type does include the 
parameter names, the names are not really part of the type - see:

https://github.com/dlang/phobos/pull/3620#issuecomment-288469685

Perhaps `ParameterIdentifierTuple` should give a compile error 
when given a function type.


Re: Mutate immutable inside shared static constructor

2024-03-23 Thread Nick Treleaven via Digitalmars-d-learn
On Saturday, 23 March 2024 at 21:53:43 UTC, Jonathan M Davis 
wrote:
Yes, it's a bug. It's a clear violation of the type system if a 
non-mutable variable is ever given a value more than once. It 
should be initialized, and then it should be treated as illegal 
to ever assign to it - or to do anything else which would 
mutate it. So, clearly, the logic in static constructors with 
regards to non-mutable variables is overly simple at the moment.


Thanks, filed:
https://issues.dlang.org/show_bug.cgi?id=24449


Mutate immutable inside shared static constructor

2024-03-23 Thread Nick Treleaven via Digitalmars-d-learn
I've not used static constructors before, but it seems like the 
following should not be allowed:


```d
import std.stdio;

immutable int x;

@safe shared static this()
{
x.writeln(); // 0
x = 5;
x.writeln(); // 5
x = 6;
x++;
assert(x == 7);
}
```
Should I file a bug to require that `x` is only written to once? 
That would make it consistent with class constructors:


```d
class C
{
immutable int x;
this()
{
x = 5;
x = 6; // error, x initialized multiple times
}
}
```


Re: Mutability issue

2024-03-23 Thread Nick Treleaven via Digitalmars-d-learn
On Saturday, 23 March 2024 at 19:30:29 UTC, Menjanahary R. R. 
wrote:
for (T candidate = T(5); candidate * candidate <= n; 
candidate += T(6)) {


When T is `const int`, the above code declares and initializes a 
constant variable:

```d
const int candidate = const int(5);
```

Then, at the end of each loop iteration, it does:
```d
candidate += const int(6);
```

So you are trying to modify a constant. Constants can only be 
initialized, never assigned.


T candidate = (n % T(2) == T(0)) ? n + T(1) : n + T(2); // 
Start from next Odd


for (;; candidate += T(2)) { // Skip even


Same here, you declare a constant then try to assign to it at the 
end of each loop iteration.


Re: length's type.

2024-02-12 Thread Nick Treleaven via Digitalmars-d-learn

On Friday, 9 February 2024 at 15:19:32 UTC, bachmeier wrote:
It's been discussed many, many times. The behavior is not going 
to change - there won't even be a compiler warning. (You'll 
have to check with the leadership for their reasons.)


Was (part of) the reason because it would disrupt existing code? 
If that was the blocker then editions are the solution.


Re: Providing implicit conversion of

2024-01-23 Thread Nick Treleaven via Digitalmars-d-learn
On Monday, 22 January 2024 at 19:49:19 UTC, Siarhei Siamashka 
wrote:
The two's complement wraparound behavior mandated by the D 
language spec is a non-technical political decision, intended 
to make life easier for the DMD compiler developers, but 
ignoring the needs of the users.


Actually it is for compatibility when porting C code to D.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Nick Treleaven via Digitalmars-d-learn
On Monday, 22 January 2024 at 19:11:50 UTC, Siarhei Siamashka 
wrote:
On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven 
wrote:
Memory safety issues are a worse class of bug than arithmetic 
bugs. The latter are reproducible if you feed them the same 
input.


Memory safety bugs are reproducible with the tools like 
`valgrind`.


Not necessarily, valgrind can execute programs too slowly for 
human input, so anything that relies on timing is difficult to 
reproduce. It also uses far more memory, it could be too much 
memory for the system.


Whereas arithmetic overflow bugs are a real PITA to debug. 
Assuming that the incorrect results are even noticed.


You're talking about debugging, whereas I'm saying you often 
don't even have a chance to *notice* memory-safety bugs, because 
they might not even occur on the development system, only on the 
production system.


And even if you know there's a memory-safety problem, you can't 
easily narrow down  where it is (without language support for 
memory-safety). With arithmetic problems it's far easier to 
narrow down which code is causing them.


But I'm strongly in favour of catching any bugs at compile-time 
(and have been since before I discovered D). I just object to 
anyone trying to downgrade the importance of automated 
memory-safety checking.


Re: Providing implicit conversion of

2024-01-22 Thread Nick Treleaven via Digitalmars-d-learn
On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer 
wrote:

The language should not allow unary unsigned anything.


This is unlikely to get fixed, just due to the nature of D's 
philosophy when it comes to C compatibility.


It would also break a lot of existing code.


I think the bigger issue is implicit conversion from unsigned to 
signed of the same bit size. In a future edition D could require 
a larger signed type in order to implicitly convert from 
unsigned. That would have caught the `long johnstone =` line.


Also signed should never convert to unsigned, though I don't 
think that's happening here.


Re: Permutations of array (slice) ?

2023-12-13 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 12 December 2023 at 16:21:46 UTC, Kevin Bailey wrote:

On Tuesday, 12 December 2023 at 15:20:23 UTC, Paul Backus wrote:
But unfortunately, the code shown now prints 120 lines of:

b

120 being suspiciously equal to 5!. The documentation[2] seems 
to imply that this should be:


b
abaaa
...


This code works for me. (The last 20+ lines are `b`):
```d
import std;
void main() {
char[] as = replicate(['a'], 5);
as[0] = 'b';
foreach (perm; as.byChar.permutations)
writeln(perm);
}
```
Try it on https://run.dlang.io/. Maybe there's some issue on your 
machine?
Also if you use `string as = "abcde";` you can see the 
permutations better.


Re: union default initialization values

2023-12-06 Thread Nick Treleaven via Digitalmars-d-learn
On Wednesday, 6 December 2023 at 12:38:35 UTC, Nick Treleaven 
wrote:
Correct. So I expected a NaN output for x. However, I wasn't 
expecting lo == 13835058055282163712 and hi == 32767 where x 
is of type real, or lo == 9221120237041090560 and hi = 0 where 
x is of type double. Based on the default initialization 
rules, I expected both lo and hi to have a value of zero 
regardless if x is of type double or real. This is what I'm 
trying to understand, how are these values derived?


ulong.sizeof is 8, like double.sizeof. So F.init.lo should have 
the same bit pattern as F.init.x because they share storage 
exactly. F.init.hi should be 0 and it is on my system. (*"If 
the union is larger than the first field, the remaining bits 
are set to 0"*). I don't know why you don't get zero for that.


Oops, you said you did get zero in that case, so all is well. 
When `x` is `real`, that may overlap with `F.hi` because `real` 
can be more than 8 bytes.


Re: union default initialization values

2023-12-06 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 5 December 2023 at 19:47:38 UTC, confuzzled wrote:

On 12/6/23 4:28 AM, Adam D Ruppe wrote:

On Tuesday, 5 December 2023 at 19:24:51 UTC, confuzzled wrote:

Given the following union

union F
{
    double x;
    struct {
    ulong lo;
    ulong hi;
    }
}


The default value of this would be `double.init`, since the 
first member of the union is a `double`, which is a kind of 
NaN. This is non-zero.




Correct. So I expected a NaN output for x. However, I wasn't 
expecting lo == 13835058055282163712 and hi == 32767 where x is 
of type real, or lo == 9221120237041090560 and hi = 0 where x 
is of type double. Based on the default initialization rules, I 
expected both lo and hi to have a value of zero regardless if x 
is of type double or real. This is what I'm trying to 
understand, how are these values derived?


ulong.sizeof is 8, like double.sizeof. So F.init.lo should have 
the same bit pattern as F.init.x because they share storage 
exactly. F.init.hi should be 0 and it is on my system. (*"If the 
union is larger than the first field, the remaining bits are set 
to 0"*). I don't know why you don't get zero for that.


Re: Inversion of conditional compilation statements

2023-12-02 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 2 December 2023 at 15:03:25 UTC, ryuukk_ wrote:
I wish we could use ``version`` as expression, to void the 
repetition:


```D
import std.stdio;

enum HasTest = version (Test) ? true : false;


Tomek Sowiński wrote this template:
```d
enum bool isVersion(string ver) = !is(typeof({
  mixin("version(" ~ ver ~ ") static assert(0);");
}));

static assert(isVersion!"assert");
static assert(!isVersion!"Broken");
```


Re: D: Convert/parse uint integer to string. (@nogc)

2023-11-27 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 27 November 2023 at 12:34:30 UTC, Nick Treleaven wrote:

On Friday, 24 November 2023 at 09:35:00 UTC, BoQsc wrote:
You can use std.conv.toChars:

```d
void main() @nogc
{
int n = 515;

import std.conv;
char[10] s = 0;
auto r = n.toChars();
assert(r.length < s.length);
size_t i;
foreach (c; r)
s[i++] = c;

import core.stdc.stdio;
puts(s.ptr);
}
```


Or, using std.experimental.allocator:

```d
void main() @nogc
{
int n = 515;

import std.conv;
import std.experimental.allocator;
import std.experimental.allocator.mallocator;
alias a = Mallocator.instance;
auto s = a.makeArray(n.toChars);
assert(s == "515");
a.dispose(s);
}
```


Re: D: Convert/parse uint integer to string. (@nogc)

2023-11-27 Thread Nick Treleaven via Digitalmars-d-learn

On Friday, 24 November 2023 at 09:35:00 UTC, BoQsc wrote:

I tried to look into https://dlang.org/phobos/std_conv.html

Most of the functions inside `std.conv` seem to be dependant on 
[Garbage Collection](https://dlang.org/spec/garbage.html).


And I couldn't find a straightforward way to produce a `string` 
value out of `uint` value.


How to convert or parse `uint` value to a `string` in `@nogc` 
way?


You can use std.conv.toChars:

```d
void main() @nogc
{
int n = 515;

import std.conv;
char[10] s = 0;
auto r = n.toChars();
assert(r.length < s.length);
size_t i;
foreach (c; r)
s[i++] = c;

import core.stdc.stdio;
puts(s.ptr);
}
```


Re: Struct copy constructor with inout

2023-11-16 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 14 November 2023 at 13:58:17 UTC, Paul Backus wrote:
On Tuesday, 14 November 2023 at 13:41:32 UTC, Steven 
Schveighoffer wrote:

```
Error: copy constructor `testinoutctor.S1.this(ref const(S1) 
s) const` is not callable using argument types `(const(S1))`

```

I'm not sure what this means. There shouldn't be a copy being 
made here, as the thing is already const. I don't understand 
this error, and it looks like a bug to me.


The error is saying that the copy constructor expects a `const` 
`this` argument, but you're passing a mutable `this` argument.


Thanks for explaining, it's a confusing error.

The error when the constructor is changed to be immutable is:
```
Error: `immutable` method `immutable_ctor.S1.this` is not 
callable using a mutable object

```
(I've made a fix to say constructor instead of method for that.)
Now I've made a fix to produce a similar error for const:
https://issues.dlang.org/show_bug.cgi?id=24248


Re: dlang.org/spec/function.html#pure-functions example

2023-10-28 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 16 October 2023 at 18:05:04 UTC, Paul wrote:
On Thursday, 12 October 2023 at 21:20:44 UTC, Jonathan M Davis 
wrote:

look like?

Types can have static members.

Basically what it comes down to is that outside of immutable 
data, pure functions only have access to their arguments and 
to what they can access via their arguments (be it by getting 
pointers from those arguments or calling other pure functions 
on them).


- Jonathan M Davis


Can I say in the general sense that when the word static is 
used it means that something is defined/declared at compile 
time?


This link should describe all the uses of `static`:
https://dlang.org/spec/attribute.html#static


Re: How to use ".stringof" to get the value of a variable and not the name of the variable (identifier) itself?

2023-10-13 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 10 October 2023 at 11:45:25 UTC, Dennis wrote:

```D
enum itoa(int i) = i.stringof;

static foreach(i; 0 .. 10) {
  mixin(create_fn!(itoa!i));
}
```


You can also do it using a string mixin:

mixin(create_fn!(mixin("`", i, "`")));

I think that's equivalent to `i.stringof` anyway.


Re: dlang.org/spec/function.html#pure-functions example

2023-10-13 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 12 October 2023 at 19:33:32 UTC, Paul wrote:
If **int x** is global mutable state, what does static mutable 
state look like?


In addition to Jonathan's reply, see:
https://dlang.org/spec/function.html#local-static-variables


Re: how to assign multiple variables at once by unpacking array?

2023-10-08 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 7 October 2023 at 17:23:40 UTC, ryuukk_ wrote:


there was a DIP for tuple/deconstruction prior to that 
question, sadly nothing came out of it,


I don't think it was formally submitted.


and now the language is frozen...


The DIP process is temporarily suspended, it may be modified. The 
priority for (most of) this year is fixing bugs. However language 
changes do happen, e.g. just this weekend switch can now declare 
a variable in the condition. Atila is working on a DIP for 
editions.


Re: C to D: please help translate this weird macro

2023-09-21 Thread Nick Treleaven via Digitalmars-d-learn
On Thursday, 21 September 2023 at 16:28:25 UTC, Nick Treleaven 
wrote:

return cast(T*)(cast(void*)(cast(char*)ptr -
__traits(getMember, T, member).offsetof)));


There's a trailing `)` that needs removing. Also pretty sure it 
can be simplified to:


return cast(T*)(cast(char*)ptr -
__traits(getMember, T, member).offsetof);


Re: C to D: please help translate this weird macro

2023-09-21 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 21 September 2023 at 02:57:07 UTC, Ki Rill wrote:

On Thursday, 21 September 2023 at 02:23:32 UTC, Ki Rill wrote:

wrote:

[...]


Translated it to this eventually:
```D
auto nk_container_of(P, T)(P ptr, T type, const(char)* member)
{
return cast(T*)(cast(void*)(cast(char*)
(ptr - __traits(getMember, type, member).offsetof)));
}
```


The 1st argument of `getMember` can just be T, like the original 
macro.

The 2nd argument needs to be a compile-time string.
Also the `char*` cast needs to apply to `ptr` before subtracting 
the offset AFAICS.


So reordering to keep type inference of `ptr`:
```d
auto nk_container_of(T, string member, P)(P ptr)
{
return cast(T*)(cast(void*)(cast(char*)ptr -
__traits(getMember, T, member).offsetof)));
}
```
(Untested)


Re: container vs standard array

2023-09-19 Thread Nick Treleaven via Digitalmars-d-learn
On Tuesday, 19 September 2023 at 19:57:34 UTC, Nick Treleaven 
wrote:
This is because a single array can be passed to a typesafe 
variadic parameter rather than elements of that array type. And 
then immutable(char) doesn't convert to string.


I think a non-variadic overload could be added to make it work 
as expected.


https://github.com/dlang/phobos/pull/8818


Re: container vs standard array

2023-09-19 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 19 September 2023 at 06:35:01 UTC, JG wrote:

On Tuesday, 19 September 2023 at 00:34:01 UTC, vino wrote:

 //auto a = Array!string("Aname");   // throws error
 auto b = Array!char("Bname");// works
 auto c = Array!string("Aname", "Bname");   // works

...
Looks to me like when it receives a single range it expects the 
elements of that range to match the type.


Yes, the first overload fails to match because U is inferred as 
immutable(char) rather than string:


this(U)(U[] values...)
if (isImplicitlyConvertible!(U, T))

This is because a single array can be passed to a typesafe 
variadic parameter rather than elements of that array type. And 
then immutable(char) doesn't convert to string.


I think a non-variadic overload could be added to make it work as 
expected.


Re: Ideas to reduce error message size?

2023-08-31 Thread Nick Treleaven via Digitalmars-d-learn
On Wednesday, 30 August 2023 at 09:24:21 UTC, Paolo Invernizzi 
wrote:
src/api3.d(49):called from here: 
`checkSql(Schema("public",  
src/dget/db.d(276): Error: template instance 
`api3.forgeSqlCheckerForSchema!(Schema("public", **BAZILLIONS of lines**>  error instantiating

 ```


The compiler could limit the call expression to a few lines 
unless the verbose flag is passed.


A similar problem exists when calling a function literal which 
errors, the whole body is printed which can be long.


Re: toLower

2023-08-18 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 17 August 2023 at 09:28:05 UTC, Joel wrote:

.map!(std.uni.toLower)
.sort!"aonlineapp.d(8): Error: none of the overloads of template 
`std.algorithm.sorting.sort` are callable using argument types 
`!("a
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/sorting.d(1925):Candidate is: `sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)`

  with `less = "a

`map` generates a range `r` whose elements can be accessed by 
mutable reference only if the result of calling the map function 
(on a source element) is a mutable reference. But 
`std.uni.toLower` returns by value, and `sort` requires `r.front` 
to be a mutable reference.


I'll look at improving the docs.


Re: Why is GC.collect `pure`

2023-08-02 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 2 August 2023 at 17:55:12 UTC, Nick Treleaven wrote:
On Wednesday, 2 August 2023 at 17:52:00 UTC, Nick Treleaven 
wrote:
Now I'm wondering why those functions are marked `pure` - they 
must affect the GC's bookkeeping state.


I guess it was because the GC's internal state is not supposed to 
be observable outside internal GC functions. I find it harder to 
accept some of those than `GC.malloc` being pure, because 
GC.disable and GC.enable will affect how long future allocations 
will take. That latency can be significant and observed by the 
program. Also conceptually they are changing GC state.


Re: Why is GC.collect `pure`

2023-08-02 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 2 August 2023 at 17:52:00 UTC, Nick Treleaven wrote:
Now I'm wondering why those functions are marked `pure` - they 
must affect the GC's bookkeeping state.


Here's the pull that added it:
https://github.com/dlang/druntime/pull/3561


Re: Why is GC.collect not @safe?

2023-08-02 Thread Nick Treleaven via Digitalmars-d-learn
On Wednesday, 2 August 2023 at 13:27:50 UTC, Steven Schveighoffer 
wrote:

On 8/2/23 7:40 AM, Nick Treleaven wrote:
Presumably an allocation like `new T` (for a type with a @safe 
constructor) can be made anywhere a call to `GC.collect` can 
be made, which may trigger a collection. So why isn't 
`GC.collect` marked @safe?


It should be. Maybe historical reasons?

One possible (but wrong) reason is that destructors can be 
unsafe. But you are correct in that allocation can cause a 
collection.


OK, thanks. I've made a pull to add `@safe` for enable, disable, 
collect, minimize:

https://github.com/dlang/dmd/pull/15493/files

Now I'm wondering why those functions are marked `pure` - they 
must affect the GC's bookkeeping state.


Re: How to free memory ater use of "new" to allocate it.

2023-07-17 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 16 July 2023 at 18:18:08 UTC, Alain De Vos wrote:

  12   │ ~this(){
  13   │ writeln("Free heap");
  14   │ import object: destroy;
  15   │ import core.memory: GC;
  16   │ i=null; // But How to force GC free ?


Firstly, be careful with class destructors and GC managed 
objects. The memory referenced by `i` may already have been freed 
by the GC when the class destructor is called - see:

https://dlang.org/spec/class.html#destructors

If you want to free GC memory when you know the allocation is 
still live, you can call __delete:

https://dlang.org/phobos/core_memory.html#.__delete

import std.stdio: writeln;

```d
void main()
{
int[] i=null;
writeln("Allocate heap");
i=new int[1];
i[9000]=5;

import core.memory;
const p = i.ptr;
assert(GC.addrOf(p) !is null);
writeln("Free heap");
__delete(i);
assert(GC.addrOf(p) is null);
}
```


Re: is ref inout redundant in: ref inout(T) opIndex(size_t index)

2023-06-21 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 19 June 2023 at 18:19:18 UTC, mw wrote:

2) `inout T` alone


Steve covered everything, though you might also like to read the 
inout spec:

https://dlang.org/spec/const3.html#inout



Re: Given an object, how to call an alias to a member function on it?

2023-05-03 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 3 May 2023 at 11:26:00 UTC, ag0aep6g wrote:

On 03.05.23 13:13, Nick Treleaven wrote:

void fun(alias method)(C c)
{
     void delegate() dg = 
     dg();
}



No, it doesn't. You're not using the alias. You're just 
accessing `c.method` directly. If the actual method weren't 
called "method", you'd get an error.


Sorry, you're right.


Re: Given an object, how to call an alias to a member function on it?

2023-05-03 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 2 May 2023 at 13:06:41 UTC, ag0aep6g wrote:

void fun(alias method)(C c)
{
void delegate() dg;
dg.funcptr = 
dg.ptr = cast(void*) c;
dg();
}


This also works:

void fun(alias method)(C c)
{
void delegate() dg = 
dg();
}



Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-31 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 27 March 2023 at 08:44:41 UTC, wjoe wrote:

e.g.: It used to be faster to ...

- pre-calculate sin/cos tables, now the memory look up cost 
more cycles than the calculation itself



...
- only redraw the parts of the screen that changed, now the 
branching is slower than to  redraw everything


Good to know, thanks.

another example is sorting - Alexei wrote a blog post about how 
a stupid and slow sorting algorithm now performs better in 
multi threading. Maybe someone remembers the title/url of the 
post ?


Not sure, but that reminds me of Andrei's blog on partitioning 
(for quicksort):

https://dlang.org/blog/2020/05/14/lomutos-comeback/

The algorithm traditionally considered slower can be faster 
because it can be optimized to work better with branch prediction.


Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-31 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 26 March 2023 at 20:36:37 UTC, ryuukk_ wrote:
Golang doesn't even have thread local storage, yet they do very 
well


Go doesn't have a solution to preventing data races at compile 
time, they just say don't share memory. But what if you 
accidentally share memory? That is *very* easy to do in Go. You 
and your users are out of luck. All you can do is run the race 
detector and pray that you happen to test all the code paths with 
it that might have data races:


The race detector only finds races that happen at runtime, so 
it can't find races in code paths that are not executed


https://go.dev/doc/articles/race_detector


Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-31 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 26 March 2023 at 20:39:21 UTC, ryuukk_ wrote:
if my code doesn't do threads, why should i put my variable 
into TLS?


I don't think writing __gshared is much of a burden. You can use 
-vtls to print out all variables that are TLS, and add that to an 
automated test to check you don't have any accidentally. I have 
thought before that a --no-threads compiler switch that does not 
link the key thread functions but makes __gshared the default 
might be a good enhancement for your use case. Then if you 
accidentally call some code that uses std.parallelism internally 
you would get a link error.



If i want fast code, why should i make use of ugly syntax?


1. If you want fast code, why aren't you using threads?
2. By default D supports threads and accidental data races are 
far worse than ugly syntax.


Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-31 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 26 March 2023 at 20:39:21 UTC, ryuukk_ wrote:
if my code doesn't do threads, why should i put my variable 
into TLS?


I don't think writing __gshared is a huge burden. You can use 
-vtls to print out all variables that are TLS, and add that to an 
automated test to check you don't have any accidentally. I have 
thought before that a --no-threads compiler switch that does not 
link the key thread functions but makes __gshared the default 
might be a good option for your use case. Then if you 
accidentally call some code that uses std.parallelism internally 
you would get a link error.



If i want fast code, why should i make use of ugly syntax?


By default D supports threads and accidental data races are far 
worse than ugly syntax.


Re: Why are globals set to tls by default? and why is fast code ugly by default?

2023-03-26 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 26 March 2023 at 18:07:03 UTC, ryuukk_ wrote:

What i find even more weird is writing fast code is ugly in D

Look at this ugly code

```D
__gshared int fast_code_ugly;
```


Because it should be rare that __gshared is used. And if you need 
it, you won't be worried about how the storage class looks 
because you'll be concentrating on if your design is thread-safe.



It should be the opposite


Then by default, @safe code can not access global variables and 
there can easily be accidental races between threads.


Re: templates and traits

2023-03-18 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 18 March 2023 at 19:22:07 UTC, Chris Katko wrote:
...


So there's multiple sub-problems to solve. I asked this years 
ago, and got 90% of the way done and then lost the code and 
cannot find the original forum post.


Maybe it was this?:
https://forum.dlang.org/post/dqzxnctucwvyhstfz...@forum.dlang.org



Re: Is comparison of shared data thread-safe?

2023-03-16 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 16 March 2023 at 12:32:34 UTC, Nick Treleaven wrote:

With -preview=nosharedaccess, I get:

int y = 2;
shared int x = y; // OK

assert(x == 2); // no error
y = x; // error


This also does not error:
```d
bool b = x == 3;
```
Filed:
https://issues.dlang.org/show_bug.cgi?id=23783


Is comparison of shared data thread-safe?

2023-03-16 Thread Nick Treleaven via Digitalmars-d-learn

With -preview=nosharedaccess, I get:

int y = 2;
shared int x = y; // OK

assert(x == 2); // no error
y = x; // error

So for the assignment to y, reading x is an error and atomicLoad 
should be used instead. But is it an oversight that reading x in 
the assert is not an error?


I have also found this in a unittest in core.atomic:

shared(size_t) i;

atomicOp!"+="(i, cast(size_t) 1);
assert(i == 1);

Is the assert somehow thread-safe?


Re: Non-ugly ways to implement a 'static' class or namespace?

2023-01-30 Thread Nick Treleaven via Digitalmars-d-learn
On Friday, 20 January 2023 at 11:28:23 UTC, thebluepandabear 
wrote:

```
final abstract class Algo {
void drawLine(Canvas c, Pos from, Pos to) { .. };
}
```

This solution seems like a bit of a hack, which is why I don't 
like it.


Interesting solution if you put `static:` in there.

Alternatively you could create a module, but then it would just 
be a function without a clear type.


Why do you want a type?

Is anyone aware of a non-ugly way to implement a 'static' class 
or namespace?


Use a struct and put `static:` after the opening brace. That's 
what GC is in core.memory.




Re: Where I download Digital Mars C Preprocessor sppn.exe?

2023-01-23 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 23 January 2023 at 17:15:30 UTC, Nick Treleaven wrote:

On Saturday, 2 April 2022 at 21:57:02 UTC, Marcone wrote:
Where I download Digital Mars C Preprocessor sppn.exe? I need 
it to use ImportC


Found this thread by googling `dlang sppn.exe`. For the record, 
it can be obtained from sppn.zip here:

http://ftp.digitalmars.com/

I didn't have it for some reason even though latest dmc is 
installed.


I then got some weird errors building druntime:

std::array not supported by DMC
std::basic_string_view not supported by DMC

I figured that dmc was not correctly installed (not sure why). So 
I downloaded dmc.zip which fixed it.


Re: Where I download Digital Mars C Preprocessor sppn.exe?

2023-01-23 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 2 April 2022 at 21:57:02 UTC, Marcone wrote:
Where I download Digital Mars C Preprocessor sppn.exe? I need 
it to use ImportC


Found this thread by googling `dlang sppn.exe`. For the record, 
it can be obtained from sppn.zip here:

http://ftp.digitalmars.com/

I didn't have it for some reason even though latest dmc is 
installed.


Re: Preventing nested struct destructor accessing stack frame

2022-12-23 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 20 December 2022 at 06:31:09 UTC, ag0aep6g wrote:

On 16.12.22 14:07, Nick Treleaven wrote:

This seems to work:

     ~this() @trusted { if ( > cast(void*)1024) i++; }

It would be better if there was a struct property to get the 
context pointer though.


A quick test suggests that the context pointer is the last item 
in `tupleof`. So this might do the trick:


~this() { if (this.tupleof[$ - 1] !is null) i++; }

I don't know if it's guaranteed to work though. Might be an 
implementation detail.


Great, thanks. The struct tupleof docs just link to the class 
tupleof docs, which say:


The order of the fields in the tuple matches the order in which 
the fields are declared.


So I think for a struct the context pointer has to come after any 
fields.


Re: Unique!struct bug - Re: unique_ptr | Unique for autoclose handle

2022-12-16 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 15 December 2022 at 20:12:12 UTC, Ali Çehreli wrote:
I think this is a bug because the documentation clearly talks 
about destroying the object:


OK: https://github.com/dlang/phobos/pull/8651


>  do we need to do some kind of deprecation?

The behavior is so different from the intention that I don't 
think anybody is using Unique anyway. :o)


Yes, at least for structs.


Re: Preventing nested struct destructor accessing stack frame

2022-12-16 Thread Nick Treleaven via Digitalmars-d-learn

On Friday, 16 December 2022 at 12:17:40 UTC, Nick Treleaven wrote:
It seems destroy clears the context pointer. Is there a way to 
test if the context pointer is null in the dtor, to prevent the 
increment?


This seems to work:

~this() @trusted { if ( > cast(void*)1024) i++; }

It would be better if there was a struct property to get the 
context pointer though.


Preventing nested struct destructor accessing stack frame

2022-12-16 Thread Nick Treleaven via Digitalmars-d-learn
This code segfaults when the GC calls the dtor after the unittest 
succeeds:


```d
unittest
{
int i;
struct S
{
~this() { i++; }
}
(*new S).destroy;
}
```

It seems destroy clears the context pointer. Is there a way to 
test if the context pointer is null in the dtor, to prevent the 
increment?


Re: pointer escaping return scope bug?

2022-12-15 Thread Nick Treleaven via Digitalmars-d-learn
On Thursday, 15 December 2022 at 20:02:38 UTC, Nick Treleaven 
wrote:

auto f() return @trusted => p ? p : v.ptr;


Whoops, that can't be @trusted unless I `assert(p)`.


Re: pointer escaping return scope bug?

2022-12-15 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 19 November 2022 at 15:24:33 UTC, Dukc wrote:
On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven 
wrote:

OK, so how do I make `lf` implicitly scope?


Have the `int*` inside it to point to a local, or assign 
another `scope int*` to it.


Thanks, this works:

```d
@safe:

struct S
{
int* p;
int[0] v; // dummy storage
auto f() return @trusted => p ? p : v.ptr;
}

void main()
{
int* p;
{
S s = S(new int);
p = s.f; // error
}
}
```


Unique!struct bug - Re: unique_ptr | Unique for autoclose handle

2022-12-15 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 14 December 2022 at 17:41:07 UTC, Ali Çehreli wrote:
I've never used Unique but I think it has a bug (or a design 
issue?): Its destructor is the following:


~this()
{
if (_p !is null)
{
destroy(_p);
_p = null;
}
}

Because _p is a pointer, destroy(_p) will not dereference and 
destroy what it points to. I think this is a bug with Unique. I 
think it should do


  destroy(*_p);


Now filed:
https://issues.dlang.org/show_bug.cgi?id=23561

Do you think it's OK to just fix this or do we need to do some 
kind of deprecation?


Re: printf, writeln, writefln

2022-12-10 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 8 December 2022 at 17:39:58 UTC, Ali Çehreli wrote:

On 12/8/22 08:21, Salih Dincer wrote:

> void stringCopy(Chars)(string source,
>  ref Chars target)

>sample.stringCopy = cTxt;  // disappeared ? char

Nothing disappeared on my system. (?)

Going off-topic, I find the expression above extremely 
confusing. I am used to assignment expression changing the 
value of the left hand side, but that expression changes cTxt. 
Very confusing...


Such obfuscations make it very hard for me to understand what 
the code is trying to demonstrate.


Yes, with function call syntax it's more understandable if an 
argument is modified.


It was bizarre and confusing that assignment syntax was 
implemented for functions and methods not explicitly marked with 
@property.




Re: How ptr arithmitic works??? It doesn't make any sense....

2022-12-04 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 4 December 2022 at 16:33:35 UTC, rempas wrote:

struct MemoryBlock {
  char* ptr;
  ulong length;
}


(MemoryBlock.sizeof is 16 on my 64-bit system).


void* ptr = cast(void*)0x7a7;

void* right() {
  return cast(MemoryBlock*)(ptr + MemoryBlock.sizeof); // Cast 
the whole expression between paranthesis. Got the right value!

}


The above adds 16 bytes to ptr.


void* wrong() {
  return cast(MemoryBlock*)ptr + MemoryBlock.sizeof; // First 
cast the `ptr` variable and then add the number. Got a wronge 
value...

}


The above adds 16 * MemoryBlock.sizeof bytes (16 * 16) to ptr, 
because ptr is cast first. Should be `+ 1` to be equivalent.


https://dlang.org/spec/expression.html#pointer_arithmetic

"the resulting value is the pointer plus (or minus) the second 
operand **multiplied by the size of the type pointed to by the 
first operand**."



char* return_address_wrong() {
  MemoryBlock* local_ptr = cast(MemoryBlock*)ptr;
  return cast(char*)(local_ptr + MemoryBlock.sizeof); // Casted 
the whole expression. BUT GOT THE WRONG VALUE Why???

}


Because you are adding to a pointer that points to a 16-byte 
block, rather than a void* which points to a single byte.



char* return_address_right() {
  MemoryBlock* local_ptr = cast(MemoryBlock*)ptr;
  return cast(char*)local_ptr + MemoryBlock.sizeof; // Now I 
first casted the `local_ptr` variable and then added the number 
but this time this gave me the right value

}


The casted pointer points to a single byte.


Re: pointer escaping return scope bug?

2022-11-27 Thread Nick Treleaven via Digitalmars-d-learn

On Friday, 25 November 2022 at 15:03:57 UTC, ShadoLight wrote:
I don't grok how `lf` can survive the local scope. Or am I 
missing something?


Perhaps because the local scope is not pushed as a separate 
(anonymous) function on the stack... if true then, yes, then 
`lf` will indeed have the same physical lifetime as main (and 
`p`)...?


On the other hand, if you add a destructor to `LockedFile`, it 
will be invoked at the end of the local scope, not the end of 
main.


Yes, the actual code does have a destructor. It's analogous to 
this:


```d
@safe:

struct S
{
private int* fps;

auto fp() return scope => fps;

this(int)
{
fps = new int;
}

@disable this();
@disable void opAssign(S);

~this() @trusted // how do we make this safe?
{
import core.memory;
GC.free(fps);
}
}

void main()
{
int* p;
{
auto lf = S(5);
p = lf.fp;
}
assert(p != null); // address escaped
}
```

That compiles with -dip1000. D doesn't seem to have a way to 
prevent the memory outliving the struct.


Just to note there is another problem when the struct is 
destroyed explicitly whilst the `fp` result is still live. But 
that could be solved by making `object.destroy` and 
`std.algorithm.move` be restricted to @system for certain structs 
like this one (either opt-in or some other mechanism). The first 
problem doesn't seem to have a solution.


Re: pointer escaping return scope bug?

2022-11-19 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 19 November 2022 at 14:52:23 UTC, ag0aep6g wrote:
That's essentially just a function that returns its pointer 
parameter. So the program boils down to this:



@safe:
int* fp(return scope int* p) { return p; }
void main()
{
int* p;
{
auto lf = new int;
p = fp(lf);
}
assert(p != null); // address escaped
}


Which is fine, as far as I can tell. `lf` is not `scope`. And 
when you pass it through `fp`, the result is still not `scope`. 
So escaping it is allowed.


You do get an error when you make `lf` `scope` (explicitly or 
implicitly). So everything seems to be in order.


OK, so how do I make `lf` implicitly scope?


pointer escaping return scope bug?

2022-11-19 Thread Nick Treleaven via Digitalmars-d-learn

Hi,
The following seems like a bug to me (reduced code, FILE* changed 
to int*):

```d
@safe:

struct LockedFile
{
private int* fps;

auto fp() return scope => fps;
}

void main()
{
int* p;
{
auto lf = LockedFile(new int);
p = lf.fp;
}
assert(p != null); // address escaped
}
```
There's no error with -dip1000.
I'll file this unless I overlooked something.


Re: Hipreme's #2 Tip of the day - Reducing .di files dependency

2022-10-24 Thread Nick Treleaven via Digitalmars-d-learn

On Sunday, 23 October 2022 at 20:12:46 UTC, Hipreme wrote:
For reducing a D Interface file dependency when generating it 
with the `-H` flag for DMD, you can't import a module on the 
top level.

Take a look at that example:


This would make a nice blog post if you have one ;-)


Re: Remove elements without losing capacity

2022-10-24 Thread Nick Treleaven via Digitalmars-d-learn

On Tuesday, 4 October 2022 at 18:18:41 UTC, Ali Çehreli wrote:
A related topic is how the "end slice" never loses that 
capacity:


void main() {
auto a = [ 1, 2 ];
auto b = a;

assert(a.capacity != 0);
assert(b.capacity != 0);

b.length--;
assert(b.capacity == 0);
assert(a.capacity != 0);// <-- Preserved
}

Aside: .capacity is an expensive operation that requires some 
levels of table lookups in the druntime. A data structure would 
benefit a lot if it kept its own capacity as a member variable.


I've now made a pull to document this:
https://github.com/dlang/dlang.org/pull/3445


Re: rotate left an array

2022-10-03 Thread Nick Treleaven via Digitalmars-d-learn

On Monday, 3 October 2022 at 18:09:05 UTC, Fausto wrote:

Hello all,

I am trying to rotate left an array.
I found a very basic way, and I am not sure if there is 
something clever than this :) maybe using slices...


Here we can't use slice assignment instead of the inner loop 
because that doesn't work for an overlapping slice. (Instead 
there's `copy` in std.algorithm).


The algorithm you wrote doesn't scale the best for speed - yours 
is the second one mentioned here:

https://www.geeksforgeeks.org/array-rotation/

Phobos has `bringToFront(arr[0..2], arr[2..$])` which does the 
same thing as a `rotate(arr, 2)` function. It seems to use the 
third algorithm from the link (or at least has the same time and 
space complexity).


The first algorithm may also work better in some cases, when 
swapping is expensive or when the result is duplicated anyway.




Re: Linker Error with Template Function

2022-09-13 Thread Nick Treleaven via Digitalmars-d-learn
On Tuesday, 13 September 2022 at 03:00:17 UTC, Kyle Ingraham 
wrote:
Any suggestions for being able to call one function for any 
instance given but maintain flexible return types?


Not sure if it helps, but you can define final methods in an 
interface, which can call virtual interface methods:

```d
interface PathConverter
{
string getValue();

final T toD(T)()
{
import std.conv : to;

return to!T(getValue());
}
}
```
Not tested as AFK.


Re: Tracing out error that causes compiler crash

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

On Sunday, 4 September 2022 at 20:48:52 UTC, solidstate1991 wrote:

What do I pass as the tester?


You can use a script as described here:
https://github.com/CyberShadow/DustMite/wiki/Detecting-a-segfault-in-dmd-itself


Re: Tracing out error that causes compiler crash

2022-09-04 Thread Nick Treleaven via Digitalmars-d-learn
On Saturday, 3 September 2022 at 21:20:01 UTC, solidstate1991 
wrote:
During unittest in my own fork of std.experimental.xml (link: 
https://github.com/ZILtoid1991/experimental.xml ), potentially 
an error so severe is present, that it causes to crash the 
compiler (both DMD and LDC2, on Windows). I was able to 
separate the issue by commenting out all unittests, then 
re-enabling them one-by-one seeing when it crashes the 
compiler, but wasn't able to track down the issues. However, 
`domimpl.d` is a 2000+ line monster, with a huge templated 
class that nests multiple other classes.


You may be able to use dustmite to automatically reduce the code 
to a minimal test case:

https://dlang.org/blog/2020/04/13/dustmite-the-general-purpose-data-reduction-tool/

Send my regards to the planet smasher.


Re: How to build DMD/Phobos on Windows

2022-09-01 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 25 August 2022 at 07:22:32 UTC, bauss wrote:


We really need a page in the documentation that describes how 
to build each component of D for each major platform.


There is on the wiki, but it's out of date:
https://wiki.dlang.org/Building_under_Windows

build.d works for dmd, but I haven't been able to build druntime 
for a while, even before the repo was merged into dmd's. (What I 
do is just rename and move dmd to a folder with existing druntime 
installed, but that doesn't really work beyond simple uses as it 
gets out of sync as the implementation changes). Last time I 
tried digger, even that didn't work. This is a problem.


Re: Convert array of tuples into array of arrays.

2022-08-31 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 31 August 2022 at 14:34:50 UTC, musculus wrote:
Hi. I have an array of tuples that I would like to convert to 
an array of arrays.

All of the elements in the tuples have matching types (string).
How would I go about doing this? Thanks!


Assuming std.typecons.Tuple, you can use `[tup.expand]` to make 
an array from a tuple.

If you mean a value sequence, you can use `[valSeq]`.


Re: Fix template parameter

2022-08-10 Thread Nick Treleaven via Digitalmars-d-learn

On Wednesday, 10 August 2022 at 06:15:39 UTC, Dom Disc wrote:
Ok, then I consider this is a bug in Phobos that should be 
corrected.


All instances of

```D
foo(T : fixedType)(T x) { }
```
should be replaced by

```D
foo(fixedType x) { }
```


Perhaps, but not necessarily. The body of foo could do 
introspection on T with static if or overloaded functions and 
produce specialised code. Even if foo doesn't do that, perhaps 
the author reserves the right to do that in future.


Or perhaps it needs to be a template to infer attributes. For 
that case, using an empty template parameter list would be 
clearer.


Re: Why are immutable array literals heap allocated?

2019-07-06 Thread Nick Treleaven via Digitalmars-d-learn

On Friday, 5 July 2019 at 23:05:32 UTC, Jonathan M Davis wrote:
Yes, I was wondering why the compiler doesn't statically 
allocate it automatically as an optimization.


It would have to be set up to store the literal somewhere else.


I was thinking the read-only data segment.

Certainly, it can't just put it on the stack, because that 
risks it going out of scope and causing memory problems. It


It can do that with small-ish sized literals if they don't escape 
(-dip1000). I think Walter may have advocated something like 
this. This one can be done even with literals of mutable elements.


no matter what optimizations the compiler does with array 
literals, that shouldn't affect whether the function can be 
@nogc. For it to affect that, it would have to be something 
that was guaranteed by the language's semantics regardless of 
whether any optimizations were being done.


Yes, just like string literals I think static allocation can be 
part of the language for immutable data.




Re: Why are immutable array literals heap allocated?

2019-07-05 Thread Nick Treleaven via Digitalmars-d-learn

On Thursday, 4 July 2019 at 11:06:36 UTC, Eugene Wissner wrote:

static immutable arr = [1, 2];

You have to spell it out that the data is static.


Yes, I was wondering why the compiler doesn't statically allocate 
it automatically as an optimization.


  1   2   >