Re: Static initialization of rectangular arrays

2019-08-29 Thread rombankzero via Digitalmars-d-learn

On Thursday, 29 August 2019 at 19:06:04 UTC, kinke wrote:
Sorry, that was wrt. the linked bugzilla and not this example 
here. - What does work is `static double[6][3] matrix = [0, 0, 
0]`, i.e., initializing each nested 1D array with a scalar 0.


I guess I'll use this workaround, though obviously it becomes 
more impractical the larger the outermost array dimension is 
¯\_(ツ)_/¯


Re: Test the return type of 'unaryFun' and 'binaryFun'.

2019-08-29 Thread Mek101 via Digitalmars-d-learn

I made the following enumerations to test the predicates.

private enum bool isUnaryPredicate(alias pred, Range) = 
is(typeof(unaryFun!(pred)((ElementType!Range).init)) == bool);
private enum bool isBinaryPredicate(alias pred, Range, V) = 
is(typeof(binaryFun!(pred)((ElementType!Range).init, V.init)) == 
bool);


Both work as expected. Thank you.


Re: Static initialization of rectangular arrays

2019-08-29 Thread kinke via Digitalmars-d-learn

On Thursday, 29 August 2019 at 18:59:22 UTC, kinke wrote:
On Thursday, 29 August 2019 at 18:11:50 UTC, Les De Ridder 
wrote:

It's a known bug[1].

As a workaround you could use a `static this()`:


Or LDC, and GDC probably too.


Sorry, that was wrt. the linked bugzilla and not this example 
here. - What does work is `static double[6][3] matrix = [0, 0, 
0]`, i.e., initializing each nested 1D array with a scalar 0.


Re: Static initialization of rectangular arrays

2019-08-29 Thread kinke via Digitalmars-d-learn

On Thursday, 29 August 2019 at 18:11:50 UTC, Les De Ridder wrote:

It's a known bug[1].

As a workaround you could use a `static this()`:


Or LDC, and GDC probably too.


Re: Static initialization of rectangular arrays

2019-08-29 Thread Les De Ridder via Digitalmars-d-learn

On Thursday, 29 August 2019 at 15:10:26 UTC, rombankzero wrote:

[...]

Is this a bug, or am I missing something? It would be really 
convenient to be able to statically initialize rectangular 
arrays in this way. Example: I have a struct that has a member 
that's a rectangular float array, but I have no way of telling 
the compiler that I want it default-initialized to all-zeroes 
(instead of NaNs)!


It's a known bug[1].

As a workaround you could use a `static this()`:

static double[6][3] matrix;

static this()
{
matrix = 0;
}

[1] https://issues.dlang.org/show_bug.cgi?id=19178


Re: Question about generation of template functions

2019-08-29 Thread Machine Code via Digitalmars-d-learn

That's right, thank you all guys. Found my mistake; should be:

serialize!(typeof(field))(__traits(getMember, output, 
fieldName));




Static initialization of rectangular arrays

2019-08-29 Thread rombankzero via Digitalmars-d-learn
Hey, everybody! I'm having Array Problems™. The documentation on 
arrays says that you can initialize all elements of a rectangular 
array with the following syntax:



double[6][3] matrix = 0; // Sets all elements to 0.


However this doesn't appear to work for static initialization:

static double[6][3] matrix = 0; // Error: cannot implicitly 
convert expression `0` of type `int` to `double[6][3]`


More confusingly, it *does* work for one-dimensional static 
arrays:



static double[6] matrix = 0; // Thumbs up from the compiler.


Is this a bug, or am I missing something? It would be really 
convenient to be able to statically initialize rectangular arrays 
in this way. Example: I have a struct that has a member that's a 
rectangular float array, but I have no way of telling the 
compiler that I want it default-initialized to all-zeroes 
(instead of NaNs)!


Re: Question about generation of template functions

2019-08-29 Thread Jesse Phillips via Digitalmars-d-learn

On Wednesday, 28 August 2019 at 20:56:25 UTC, Machine Code wrote:
I was writing a recursive function that uses template, I 
thought it would generate the proper template function on the 
fly to match the type in the parameter but it seems to not so 
so and try to use the called function, resulting in the error:


Error: function foo.serialize!(B).serialize(ref B output) is 
not callable using argument types (A)
   cannot pass argument output of type A to parameter ref 
B output
Error: template instance `foo.serialize!(A)` error 
instantiating


Code:



void serialize(T)(ref T output)
{
import std.traits : hasUDA, getUDAs, isAggregateType;
import std.meta : Alias;

foreach(fieldName; __traits(derivedMembers, T))
{
alias field = Alias!(__traits(getMember, T, fieldName));
static if(isAggregateType!(typeof(field)))
{
serialize!(typeof(field))(output);
}
static if(hasUDA!(field, Attr))
{
enum className = getUDAs!(field, Attr)[0];
writefln("className = [%s]", className);
}
}
}


You're asking it to be the field type but passing it output.


serialize!(typeof(field))(output);



Re: Is removing elements of AA in foreach loop safe?

2019-08-29 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, August 29, 2019 4:11:58 AM MDT berni via Digitalmars-d-learn 
wrote:
> Iterating of some structure and removing elements thereby is
> always errorprone and should be avoided. But: In case of AA, I've
>
> got the feeling, that it might be safe:
> > foreach (k,v;ways)
> >
> > if (v.empty)
> >
> > ways.remove(k);
>
> Do you agree? Or is there a better way to achieve this?

No, it's not safe to do that. If you insert or remove any elements from an
AA while looping over it, you're going to have weird behavior. If you want
to remove elements in a loop, then you'll need to do something like put each
key that you want to remove in a dynamic array while looping over the AA and
then loop over the dynamic array to remove the elements from the AA.

- Jonathan M Davis





Re: Test the return type of 'unaryFun' and 'binaryFun'.

2019-08-29 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 29 August 2019 at 08:58:18 UTC, Mek101 wrote:
As the title says, is there a way to test the return type of 
the 'unaryFun' and 'binaryFun' templates from 'std.functional'?


I have the following code, and I want to to be sure that 
'predicate' returns a boolean, but neither 
'is(typeof(predicate) == bool)' or 'is(ReturnType!predicate == 
bool)' seem to work.



private alias NullSized = Nullable!(size_t, size_t.max);


public NullSized indexOf(alias pred = "a == b", Range, V)(Range 
array, V value)

if((isRandomAccessRange!Range || isStaticArray!Range))
{
alias predicate = binaryFun!pred;

for(size_t i = 0; i < array.length; i++)
if(predicate(array[i], value))
return NullSized(i);
return NullSized.init;
}


You'll need to test calling the predicate with the actual types 
it will be processing - something like 
is(typeof(predicate(array[0], value)) == bool). You could (and 
quite possibly should) do this in the template constraint.


The reason is binaryFun actually returns a generic function - a 
template that needs to know its actual argument types. For fun, 
you could actually test is(typeof(predicate!(ElementType!Range, 
V)) == bool).


--
  Simen


Re: Input/Output multiple values from function

2019-08-29 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 29 August 2019 at 10:39:44 UTC, Jabari Zakiya wrote:
The values modpg, res_0, restwins, and resinvrs are constant 
(immutable) values that are generated at run time. They are 
global/shared and used inside threads.


So this process is initializing them at the start of the 
program, based on the input values to it.


Great - then you can use shared(immutable(uint)[]). You should be 
able to convert from immutable(uint[]) to that without issue. 
There's a utility function in std.exception called assumeUnique 
that can be used for conversion to immutable that may be more 
informative than cast(immutable):


shared(uint) modpg;
shared(uint) res_0;
shared(immutable(uint)[]) restwins;
shared(immutable(uint)[]) resinvrs;

auto genPGparameters(int i) {
import std.typecons;
import std.exception;
// Showing both cast and assumeUnique:
return tuple(1u, 2u, cast(immutable)[3u], [4u].assumeUnique);
}

unittest {
import std.meta : AliasSeq;
int pg;
// No need for temporaries:
AliasSeq!(modpg, res_0, restwins, resinvrs) = 
genPGparameters(pg);

}


The compiler only has a problem, it seems, with the arrays and 
not the single values.


Correct - since there are no indirections in a uint, you can 
assign directly to a shared(uint) - nobody else will have a 
non-shared pointer to that uint, so it's somewhat safe. If you do 
the same with uint[], you'll still have a pointer to the same 
values, and changing a value that says it's thread-local (no 
shared) will change values that is shared with the rest of the 
program. There are some issues with the current shared design, 
but this is what it's intended to do.


--
  Simen


Re: Input/Output multiple values from function

2019-08-29 Thread Jabari Zakiya via Digitalmars-d-learn

On Thursday, 29 August 2019 at 09:04:17 UTC, Simen Kjærås wrote:
On Wednesday, 28 August 2019 at 13:11:46 UTC, Jabari Zakiya 
wrote:

[...]


Reduced example:

unittest {
int[] a;
// cannot implicitly convert expression a of type int[] to 
shared(int[])

shared int[] b = a;
}

This is because an int[] is mutable and thread-local, while 
shared(int[]) is mutable and shared. Shared mutable data must 
be guarded closely, preferably behind a mutex or similar. 
Assigning the value of `a` to `b` above would leave a mutable 
reference to the shared data on a thread, and could easily lead 
to race conditions.


In order to fix this issue, consider several things:

Do modpg and friends really need to be shared? Removing 
shared() from them will still make them available to other 
parts of your code, but they will be thread-local instead. If 
you're not doing threaded work, that should be perfectly fine.


Can they be immutable? If they're initialized once and never 
changed, this could be a good solution.


If they need to be shared and mutable, have you protected them 
enough from race conditions? Are there possible situations 
where other threads may be accessing them while one thread is 
writing to them?


Multi-threaded programming is hard, and requires a lot more 
knowledge than we have about your project from the code you've 
posted, so only you can answer these questions. If you're 
unsure, you can probably just remove shared() from modpg and 
friends.


--
  Simen


The values modpg, res_0, restwins, and resinvrs are constant 
(immutable) values that are generated at run time. They are 
global/shared and used inside threads.


So this process is initializing them at the start of the program, 
based on the input values to it.


The compiler only has a problem, it seems, with the arrays and 
not the single values.


Is removing elements of AA in foreach loop safe?

2019-08-29 Thread berni via Digitalmars-d-learn
Iterating of some structure and removing elements thereby is 
always errorprone and should be avoided. But: In case of AA, I've 
got the feeling, that it might be safe:



foreach (k,v;ways)
if (v.empty)
ways.remove(k);


Do you agree? Or is there a better way to achieve this?


Re: Input/Output multiple values from function

2019-08-29 Thread Simen Kjærås via Digitalmars-d-learn

On Wednesday, 28 August 2019 at 13:11:46 UTC, Jabari Zakiya wrote:

When I do this:

uint a; uint b; uint[] c; uint[] d;
  AliasSeq!(a, b, c, d) = genPGparameters(pg);
  modpg= a;
  res_0= b;
  restwins = c;
  resinvrs = d;

the compiler (ldc2 1.17) says:

D Projects ~/D/bin/ldc2 --release -O3 twinprimes_ssoznew1.d
twinprimes_ssoznew1.d(170): Error: cannot implicitly convert 
expression c of type uint[] to shared(uint[])
twinprimes_ssoznew1.d(171): Error: cannot implicitly convert 
expression d of type uint[] to shared(uint[])


where modpg, res_0; restwins, resinvrs are shared (global) 
variables.


Reduced example:

unittest {
int[] a;
// cannot implicitly convert expression a of type int[] to 
shared(int[])

shared int[] b = a;
}

This is because an int[] is mutable and thread-local, while 
shared(int[]) is mutable and shared. Shared mutable data must be 
guarded closely, preferably behind a mutex or similar. Assigning 
the value of `a` to `b` above would leave a mutable reference to 
the shared data on a thread, and could easily lead to race 
conditions.


In order to fix this issue, consider several things:

Do modpg and friends really need to be shared? Removing shared() 
from them will still make them available to other parts of your 
code, but they will be thread-local instead. If you're not doing 
threaded work, that should be perfectly fine.


Can they be immutable? If they're initialized once and never 
changed, this could be a good solution.


If they need to be shared and mutable, have you protected them 
enough from race conditions? Are there possible situations where 
other threads may be accessing them while one thread is writing 
to them?


Multi-threaded programming is hard, and requires a lot more 
knowledge than we have about your project from the code you've 
posted, so only you can answer these questions. If you're unsure, 
you can probably just remove shared() from modpg and friends.


--
  Simen


Test the return type of 'unaryFun' and 'binaryFun'.

2019-08-29 Thread Mek101 via Digitalmars-d-learn
As the title says, is there a way to test the return type of the 
'unaryFun' and 'binaryFun' templates from 'std.functional'?


I have the following code, and I want to to be sure that 
'predicate' returns a boolean, but neither 'is(typeof(predicate) 
== bool)' or 'is(ReturnType!predicate == bool)' seem to work.



private alias NullSized = Nullable!(size_t, size_t.max);


public NullSized indexOf(alias pred = "a == b", Range, V)(Range 
array, V value)

if((isRandomAccessRange!Range || isStaticArray!Range))
{
alias predicate = binaryFun!pred;

for(size_t i = 0; i < array.length; i++)
if(predicate(array[i], value))
return NullSized(i);
return NullSized.init;
}