Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Thursday, 20 January 2022 at 04:38:39 UTC, forkit wrote:




all done ;-)

// ---

module test;

import std.stdio : writeln;
import std.range : iota, isForwardRange, hasSlicing, hasLength, 
isInfinite;

import std.array : array, Appender;
import std.random : Random, unpredictableSeed, dice, choice;
import std.algorithm : map, uniq, canFind;

@safe:

Random rnd;

static this()
{
  rnd = Random(unpredictableSeed);
}

void main()
{
int recordsNeeded = 2;
int boolValuesNeeded = 3;

uint[] uniqueIDs;
makeUniqueIDs(uniqueIDs, recordsNeeded);

uint[][] tuples;
createBoolMatrix(tuples, recordsNeeded, boolValuesNeeded);

uint[][uint][] records = CreateTupleDictionary(uniqueIDs, 
tuples);

processRecords(records);

}

auto CreateTupleDictionary(ref uint[] ids, ref uint[][] tuples)
{
uint[][uint][] records;

foreach(i, id; ids)
records ~= [ ids[i] : tuples[i] ];

return records.dup;
}

void processRecords(T)(const ref T t) if (isForwardRange!T && 
hasSlicing!T && hasLength!T && !isInfinite!T)

{
t.writeln;

// output from above should look like this:
// [[999583661:[1, 1, 0]], [999273256:[1, 1, 1]]]

// hoping to explore parallel here too...
}

void createBoolMatrix(ref uint[][] m, size_t numberOfTuples, 
size_t numberOfBoolsInTuple)

{
m = iota(numberOfTuples)
.map!(i => iota(numberOfBoolsInTuple)
.map!(numberOfBoolsInTuple => cast(uint) 
rnd.dice(0.6, 1.4))

.array).array;
}


void makeUniqueIDs(ref uint[] arr, size_t sz)
{
arr.reserve(sz);

// id needs to be 9 digits, and needs to start with 999
int[] a = iota(999_000_000, 1_000_000_000).array;
// above will contain 1_000_000 records that we can choose 
from.


int i = 0;
uint x;
while(i != sz)
{
   x = cast(uint)a.choice(rnd);

   // ensure every id added is unique.
   if (!arr.canFind(x))
   {
   arr ~= x;
   i++;
   }
}
}

// ---



Re: number ranges

2022-01-19 Thread Salih Dincer via Digitalmars-d-learn

Hi,

It looks so delicious.  Thank you.

On Wednesday, 19 January 2022 at 18:59:10 UTC, Ali Çehreli wrote:


And adding length() was easy as well.

Finally, I have provided property functions instead of allowing 
direct access to members.


It doesn't matter as we can't use a 3rd parameter.  But it 
doesn't work for any of these types: real, float, double.


My solution:
```d
  size_t length() inout {
//return last_ - first_ + 1 - empty_;/*
auto len = 1 + last_ - first_;
return cast(size_t)len;//*/
  }
```
But it only works on integers. In this case, we have two options! 
The first is to require the use of integers, other 3 parameter 
usage:

```d
// ...
  size_t length() inout {
auto len = 1 + (last - front) / step;
return cast(size_t)len;
  }
} unittest {
  enum { ira = 0.1,
 irb = 2.09,
 irc = 0.11
   }
  auto test = inclusiveRange(ira, irb, irc);
  assert(test.count == 19);

  auto arr = iota(ira, irb, irc).array;
  assert(test.length == arr.length);
}
```

Salih


Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Thursday, 20 January 2022 at 04:00:59 UTC, forkit wrote:

void makeUniqueIDs(ref uint[] arr, size_t sz)
{
  ...
}


arrg!

what was i thinking! ;-)

// ---
void makeUniqueIDs(ref uint[] arr, size_t sz)
{
arr.reserve(sz);

// id needs to be 9 digits, and needs to start with 999
int[] a = iota(999_000_000, 1_000_000_000).array;
// above will contain 1_000_000 records that we can choose 
from.


int i = 0;
uint x;
while(i != sz)
{
   x = cast(uint)a.choice(rnd);

   // ensure every id added is unique.
   if (!arr.canFind(x))
   {
   arr ~= x;
   i++;
   }
   else
   i--;
}
}


//--




Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Thursday, 20 January 2022 at 00:30:44 UTC, H. S. Teoh wrote:


Do the id's have to be unique?


yep...

I'm almost there ;-)

// ---
module test;

import std.stdio : writeln;
import std.range : iota, isForwardRange, hasSlicing, hasLength, 
isInfinite;

import std.array : array, Appender;
import std.random : Random, unpredictableSeed, dice, choice;
import std.algorithm : map, uniq;

@safe:

Random rnd;

static this()
{
  rnd = Random(unpredictableSeed);
}

void main()
{
int recordsNeeded = 5;

uint[] uniqueIDs;
makeUniqueIDs(uniqueIDs, recordsNeeded);
writeln(uniqueIDs);

uint[][] mArrBool;

// e.g: create a matrix consisting of 5 tuples,
// with each tuple containing 3 random bools (0 or 1)
createBoolMatrix(mArrBool,recordsNeeded, 3);

// process just writeln's it's argument at the moment
process(mArrBool); // [[1, 1, 1], [0, 0, 1], [1, 1, 1], [1, 
1, 1], [1, 1, 0]]


// to do (integrate a single value taken from uniqueIDs so 
that each tuple looks like this: [999575454:[1, 1, 1]]

// e.g.
// processRecords(records);
// output from above should look like this below:
// [ [999575454:[1, 1, 1]], [999704246:[0, 0, 1]], 
[69331:[1, 1, 1]], [999678591:[1, 1, 1]], [999691754:[1, 1, 
0]] ]


}

void createBoolMatrix(ref uint[][] m, size_t numberOfTuples, 
size_t numberOfBoolsInTuple)

{
m = iota(numberOfTuples)
.map!(i => iota(numberOfBoolsInTuple)
.map!(numberOfBoolsInTuple => cast(uint) 
rnd.dice(0.6, 1.4))

.array).array;
}

void process(T)(const ref T t) if (isForwardRange!T && 
hasSlicing!T && hasLength!T && !isInfinite!T)

{
t.writeln;
}

void processRecords(T)(const ref T t) if (isForwardRange!T && 
hasSlicing!T && hasLength!T && !isInfinite!T)

{
t.writeln;
}


void makeUniqueIDs(ref uint[] arr, size_t sz)
{
// id needs to be 9 digits, and needs to start with 999
int[] a = iota(999_000_000, 1_000_000_000).array; // can 
produce a max of 1_000_000 records.


Appender!(uint[]) appndr;
// pre-allocate space to avoid costly reallocations
appndr.reserve(sz+1);

foreach(value; 1..(sz + 1))
appndr ~= cast(uint)a.choice(rnd);

// just interesting to see often this asserts.
//assert(appndr[].array == appndr[].uniq.array);

arr = appndr[].uniq.array;

// function should not return if this asserts (i.e. app will 
exit)

assert(arr[].array == arr[].uniq.array);
}
// ---



Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn

On Thursday, 20 January 2022 at 01:14:51 UTC, Adam Ruppe wrote:
On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer 
wrote:
static foreach(member; __traits(allMembers, 
Manager))


member here is a string, not the member. I prefer to call it 
memberName.


Then you __traits(getMember, Manager, memberName) to actually 
get the alias you can pass to getAttributes.


Thanks, that fixed it. Final working version for anyone who finds 
this thread:


```d
import std.traits;
import std.stdio;

enum Runnable;

struct SubSystem
{
void run()
{
writeln("SubSystem ran");
}
}

struct Manager
{
@Runnable SubSystem subsystem;

void run()
{
static foreach(memberName; __traits(allMembers, Manager))
{
static foreach (attribute; __traits(getAttributes, 
__traits(getMember, Manager, memberName)))

{
static if (is(attribute == Runnable))
{
__traits(getMember, Manager, 
memberName).run();

}
}
}
}
}


void main()
{
Manager m;
m.run();
}
```


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Adam Ruppe via Digitalmars-d-learn

On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer wrote:
static foreach(member; __traits(allMembers, 
Manager))


member here is a string, not the member. I prefer to call it 
memberName.


Then you __traits(getMember, Manager, memberName) to actually get 
the alias you can pass to getAttributes.


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 21:49:12 UTC, Adam D Ruppe wrote:
I never use most of std.traits, they just complicate things. 
Bleh idk, I wouldn't bother with it and loop through the 
__traits instead.


Unless I'm missing something obvious this has to be a DMD bug, 
because this prints nothing:


```d
import std.traits;
import std.stdio;

enum Runnable;

struct SubSystem
{
void run()
{
writeln("SubSystem ran");
}
}

struct Manager
{
@Runnable SubSystem subsystem;

void run()
{
static foreach(member; __traits(allMembers, Manager))
{
static foreach (attribute; 
__traits(getAttributes, member))

{
static if (attribute == Runnable)
{
__traits(child, Manager, member).run();
}
}
}
}
}

void main()
{
Manager m;
m.run();
}
```

The `__traits(getAttributes, member)` call always returns an 
empty tuple. Calling `__traits(getAttributes, Manager.subsystem)` 
manually works as expected.


Re: automate tuple creation

2022-01-19 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 20, 2022 at 12:12:56AM +, forkit via Digitalmars-d-learn wrote:
[...]
> createBoolAssociativeMatrix(mArrBool,3, 2);
> 
> [ [1000:[1, 0]], [1001:[1, 1]], [1001:[1, 0]]]
> 
> 
> where 1000 is some random id...

Do the id's have to be unique?  If not, std.random.uniform() would do
the job.

If they have to be unique, you can either use a sequential global
counter (a 64-bit counter will suffice -- you'll won't exhaust it for at
least 60+ years of bumping the counter once per CPU tick at 8.4 GHz), or
use an AA of ids already generated and just call uniform() to generate a
new one until it doesn't collide anymore.


T

-- 
A mathematician learns more and more about less and less, until he knows 
everything about nothing; whereas a philospher learns less and less about more 
and more, until he knows nothing about everything.


Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 21:59:15 UTC, forkit wrote:




so at the moment i can get a set number of tuples, with a set 
number of bool values contained within each tuple.


e.g.
createBoolMatrix(mArrBool,3, 2);
[[1, 0], [1, 1], [1, 0]]

my next challenge (more for myself, but happy for input)..

is to enhance this to an return an associative array:

e.g

createBoolAssociativeMatrix(mArrBool,3, 2);

[ [1000:[1, 0]], [1001:[1, 1]], [1001:[1, 0]]]


where 1000 is some random id...



Re: why there is a [] at the end of assocArray

2022-01-19 Thread MichaelBi via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 16:36:36 UTC, Ali Çehreli wrote:

On 1/19/22 06:06, michaelbi wrote:
On Wednesday, 19 January 2022 at 13:21:32 UTC, Stanislav 
Blinov wrote:
On Wednesday, 19 January 2022 at 13:15:35 UTC, michaelbi 
wrote:



[...]



[...]


...because there's an empty line at the end of input.txt?


i got it, though i still don't know where the [] come from. i 
just add strip here: a=>a.idup.strip


Works for me on Linux. Perhaps there is an issue with Windows 
line endings?


In any case, the .strip above would not be eliminating empty 
lines; you need to filter them out e.g. with


  byLine.filter!(line => !line.empty)

Aside: Instead of copying the lines with .idup explicitly, 
there is .byLineCopy that already does that.


Ali


I am using windows.
Thanks a lot for introducing those funcs. Now I am feeling the 
D’s quite interesting and powerful :)


Re: how to print "111000" out into 0b111000

2022-01-19 Thread MichaelBi via Digitalmars-d-learn
On Wednesday, 19 January 2022 at 15:41:31 UTC, Brian Callahan 
wrote:

On Wednesday, 19 January 2022 at 15:01:29 UTC, michaelbi wrote:

as captioned... thx.


```d
import std.stdio;
import std.conv;

void main()
{
writefln("0b%b", to!int("111000", 2));
}
```


Got it, thanks


Re: automate tuple creation

2022-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 1/19/22 15:21, H. S. Teoh wrote:
> On Wed, Jan 19, 2022 at 02:33:02PM -0800, Ali Çehreli via 
Digitalmars-d-learn wrote:

> [...]
>> // Returning a dynamically allocated array looks expensive
>> // here. Why not use a struct or std.typecons.Tuple instead?
>
> Premature optimization. ;-)

Not in this case because I am pointing at premature pessimization. :) 
There is no reason to use two-element dynamic arrays when uint[2], 
Tuple!(uint, uint), and structs are available.


> There's nothing wrong with allocating an
> array.

Agreed.

Ali



Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 22:35:58 UTC, Ali Çehreli wrote:




so I combined ideas from all responses:

// --
module test;

import std.stdio : writeln;
import std.range : iota, isForwardRange, hasSlicing, hasLength, 
isInfinite, array;

import std.random : Random, unpredictableSeed, dice;
import std.algorithm : map;

@safe:

Random rnd;

static this()
{
  rnd = Random(unpredictableSeed);
}

void main()
{
uint[][] mArrBool;

// e.g: create a matrix consisting of 5 tuples, with each 
tuple containing 3 random bools (0 or 1)

createBoolMatrix(mArrBool,5, 2);

process(mArrBool);
}

void createBoolMatrix(ref uint[][] m, size_t numberOfTuples, 
size_t numberOfBoolsInTuple)

{
m = iota(numberOfTuples)
.map!(i => iota(numberOfBoolsInTuple)
.map!(numberOfBoolsInTuple => cast(uint) 
rnd.dice(0.6, 1.4))

.array).array;
}

void process(T)(const ref T t) if (isForwardRange!T && 
hasSlicing!T && hasLength!T && !isInfinite!T)

{
t.writeln;
}

//--



Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 23:22:17 UTC, forkit wrote:




oops

// e.g: create a matrix consisting of 5 tuples, with each tuple 
containing 3 random bools (0 or 1)

createBoolMatrix(mArrBool,5, 3);


Re: automate tuple creation

2022-01-19 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Jan 19, 2022 at 02:33:02PM -0800, Ali Çehreli via Digitalmars-d-learn 
wrote:
[...]
> // Returning a dynamically allocated array looks expensive
> // here. Why not use a struct or std.typecons.Tuple instead?

Premature optimization. ;-)  There's nothing wrong with allocating an
array.

If you're worried about memory efficiency, you could allocate the entire
matrix in a single block and just assemble slices of it in the outer
block, like this:

uint[][] createBoolMatrix(size_t count) {
auto buffer = new uint[count*count];
return iota(count).map!(i => buffer[count*i .. count*(i+1)])
.array;
}

This lets you do only 2 GC allocations instead of (1+count) GC
allocations.  May help with memory fragmentation if `count` is large and
you create a lot of these things.  But I honestly wouldn't bother with
this unless your memory profiler is reporting a problem in this aspect
of your program.  It just adds complexity to your code (== poorer
long-term maintainability) for meager benefits.


T

-- 
What do you call optometrist jokes? Vitreous humor.


Re: automate tuple creation

2022-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 1/19/22 14:33, Ali Çehreli wrote:

> Random rnd;
>
> shared static this() {
>rnd = Random(unpredictableSeed);
> }

But that's a mistake: If rnd is thread-local like that, it should be 
initialized in a 'static this' (not 'shared static this'). Otherwise, 
only the main thread's 'rnd' would be randomized, which is the only 
thread that executes 'shared static this' blocks.


Ali



Re: automate tuple creation

2022-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 1/19/22 13:59, forkit wrote:

> void createBoolMatrix(ref uint[][] m)
> {
>  auto rnd = Random(unpredictableSeed);

That works but would be unnecessarily slow and be against the idea of 
random number generators. The usual approach is, once you have a 
randomized sequence, you just continue using it. For example, I move rnd 
to module scope and initialize it once.


Random rnd;

shared static this() {
  rnd = Random(unpredictableSeed);
}

auto randomValue() {
  return cast(uint)rnd.dice(0.6, 1.4);
}

// Returning a dynamically allocated array looks expensive
// here. Why not use a struct or std.typecons.Tuple instead?
auto randomTuple() {
  return [ randomValue(), randomValue() ];
}

void createBoolMatrix(ref uint[][] m, size_t count)
{
  import std.algorithm : map;
  import std.range : iota;
  m = count.iota.map!(i => randomTuple()).array;
}

Ali



Re: automate tuple creation

2022-01-19 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Jan 19, 2022 at 09:59:15PM +, forkit via Digitalmars-d-learn wrote:
> so I have this code below, that creates an array of tuples.
> 
> but instead of hardcoding 5 tuples (or hardcoding any amount of
> tuples), what I really want to do is automate the creation of
> how-ever-many tuples I ask for:
> 
> i.e.
> 
> instead of calling this: createBoolMatrix(mArrBool);
> I would call something like this: createBoolMatrix(mArrBool,5); //
> create an array of 5 typles.

Why can't you just use a loop to initialize it?

uint[][] createBoolMatrix(size_t n) {
auto result = new uint[][n]; // allocate outer array
foreach (ref row; result) {
row = new uint[n]; // allocate inner array
foreach (ref cell; row) {
cell = cast(uint) rnd.dice(0.6, 1.4);
}
}
return result;
}

Or, if you wanna use those new-fangled range-based idioms:

uint[][] createBoolMatrix(size_t n) {
return iota(n)
.map!(i => iota(n)
.map!(j => cast(uint) rnd.dice(0.6, 1.4))
.array)
.array;
}


T

-- 
Verbing weirds language. -- Calvin (& Hobbes)


Re: automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 21:59:15 UTC, forkit wrote:




oh. that randomShuffle was unnecessary ;-)



automate tuple creation

2022-01-19 Thread forkit via Digitalmars-d-learn

so I have this code below, that creates an array of tuples.

but instead of hardcoding 5 tuples (or hardcoding any amount of 
tuples),
what I really want to do is automate the creation of 
how-ever-many tuples I ask for:


i.e.

instead of calling this: createBoolMatrix(mArrBool);
I would call something like this: createBoolMatrix(mArrBool,5); 
// create an array of 5 typles.


Some ideas about direction would be welcome ;-)


// ---
module test;

import std.stdio;
import std.range;
import std.traits;
import std.random;

@safe:

void main()
{
uint[][] mArrBool;
createBoolMatrix(mArrBool);
process(mArrBool);
}

void process(T)(const ref T t) if (isForwardRange!T && 
!isInfinite!T)

{
t.writeln; // sample output -> [[0, 1], [1, 0], [1, 1], [1, 
1], [1, 1]]

}

void createBoolMatrix(ref uint[][] m)
{
auto rnd = Random(unpredictableSeed);

// btw. below does register with -profile=gc
m = [ [cast(uint)rnd.dice(0.6, 1.4), cast(uint)rnd.dice(0.4, 
1.6)].randomShuffle(rnd),
  [cast(uint)rnd.dice(0.6, 1.4), cast(uint)rnd.dice(0.4, 
1.6)].randomShuffle(rnd),
  [cast(uint)rnd.dice(0.6, 1.4), cast(uint)rnd.dice(0.4, 
1.6)].randomShuffle(rnd),
  [cast(uint)rnd.dice(0.6, 1.4), cast(uint)rnd.dice(0.4, 
1.6)].randomShuffle(rnd),
  [cast(uint)rnd.dice(0.6, 1.4), cast(uint)rnd.dice(0.4, 
1.6)].randomShuffle(rnd)

];
}
// --


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Adam D Ruppe via Digitalmars-d-learn
On Wednesday, 19 January 2022 at 21:44:57 UTC, Jack Stouffer 
wrote:
The error is actually coming from trying to use the result of 
getSymbolsByUDA in the right part of the `static foreach`


huh..

I never use most of std.traits, they just complicate things. Bleh 
idk, I wouldn't bother with it and loop through the __traits 
instead.




Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 20:53:29 UTC, Adam D Ruppe wrote:
So you want to `__traits(child, system, this).run()` and it 
should work - the traits child will re-attach a this value.


The error is actually coming from trying to use the result of 
getSymbolsByUDA in the right part of the `static foreach`, not 
the call to the `run` function. Which was odd to me because I 
thought it just returned a `AliasSeq`.


Here's a link to the erroring code with your traits change:

https://run.dlang.io/is/gO84ox


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Adam D Ruppe via Digitalmars-d-learn
On Wednesday, 19 January 2022 at 20:46:17 UTC, Jack Stouffer 
wrote:
static foreach(system; getSymbolsByUDA!(Manager, 
Runnable))

{
system.run();
onlineapp.d(16): Error: value of `this` is not known at compile 
time


The getSymbols returns aliases, meaning you hit what I wrote 
about a few days ago:


http://dpldocs.info/this-week-in-d/Blog.Posted_2022_01_10.html#tip-of-the-week

The `this` is a runtime value and all the other `static` things 
work on compile time info.


So you want to `__traits(child, system, this).run()` and it 
should work - the traits child will re-attach a this value.


Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn
I'm trying to use getSymbolsByUDA in order to loop over all of 
the members in a struct with a certain UDA, and then call a 
function on the member. The plan is to use this to avoid looping 
over an array of function pointers.


However, the compiler is giving a strange error and the 
documentation of getSymbolsByUDA is unhelpful, as there are no 
practical use-case examples.


Here's a very simplified version of my code

```d
import std.traits;

enum Runnable;

struct SubSystem
{
void run();
}

struct Manager
{
@Runnable SubSystem subsystem;

void run()
{
static foreach(system; getSymbolsByUDA!(Manager, 
Runnable))

{
system.run();
}
}
}

void main()
{
Manager m;
m.run();
}

```

Result:

```
onlineapp.d(16): Error: value of `this` is not known at compile 
time

```

This seems to me to be the logical way to write this code. What 
am I missing?




Re: number ranges

2022-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 1/19/22 04:51, Salih Dincer wrote:

> Is it okay to swap places instead of throwing an error?

I would be happier if my potential mistake is caught instead of the 
library doing something on its own.


> Let's also
> implement BidirectionalRange, if okay.

I had started experimenting with that as well. The implementation below 
does not care if popFront() or popBack() are called on empty ranges. The 
programmer must be careful. :)


> "Does it reverse the result
> in case ```a > b``` like we
> did with foreach_reverse()"

No, it should not reverse the direction that way because we already have 
retro. :)


  inclusiveRange(1, 10).retro;

Improving the range as a BidirectionalRange requires three more 
functions: save(), back(), and popBack().


I am also removing the silly 'const' qualifiers from member functions 
because a range object is supposed to be mutated. I came to that 
conclusion after realizing that save() cannot be 'const' because it 
break isForwardRange (which is required by isBidirectionalRange). Ok, I 
will change all 'const's to 'inout's in case someone passes an object to 
a function that takes by 'const' and just applies e.g. empty() on it.


And adding length() was easy as well.

Finally, I have provided property functions instead of allowing direct 
access to members.


struct InclusiveRange(T) {
  import std.format : format;

  T first_;
  T last_;
  bool empty_;

  this(U)(in U first, in U last)
  in (first <= last, format!"Invalid range: [%s,%s]."(first, last)) {
this.first_ = first;
this.last_ = last;
this.empty_ = false;
  }

  T front() inout {
return first_;
  }

  bool empty() inout {
return empty_;
  }

  void popFront() {
if (first_ == last_) {
  empty_ = true;

} else {
  ++first_;
}
  }

  auto save() inout {
return this;
  }

  T back() inout {
return last_;
  }

  void popBack() {
if (first_ == last_) {
  empty_ = true;

} else {
  --last_;
}
  }

  size_t length() inout {
return last_ - first_ + 1 - empty_;
  }
}

auto inclusiveRange(T)(in T first, in T last) {
  return InclusiveRange!T(first, last);
}

unittest {
  // Invalid range should throw
  import std.exception : assertThrown;

  assertThrown!Error(inclusiveRange(2, 1));
}

unittest {
  // Should not be possible to have an empty range
  import std.algorithm : equal;

  auto r = inclusiveRange(42, 42);
  assert(!r.empty);
  assert(r.equal([42]));
}

unittest {
  // Should be able to represent all values of a type
  import std.range : ElementType;
  import std.algorithm : sum;

  auto r = inclusiveRange(ubyte.min, ubyte.max);
  static assert(is(ElementType!(typeof(r)) == ubyte));

  assert(r.sum == (ubyte.max * (ubyte.max + 1)) / 2);
}

unittest {
  // Should produce the last value
  import std.algorithm : sum;

  assert(inclusiveRange(1, 10).sum == 55);
}

unittest {
  // Should work with negative values
  import std.algorithm : equal;
  assert(inclusiveRange(-3, 3).equal([-3, -2, -1, 0, 1, 2, 3]));
  assert(inclusiveRange(-30, -27).equal([-30, -29, -28, -27]));
}

unittest {
  // length should be correct
  import std.range : enumerate, iota;

  enum first = 5;
  enum last = 42;
  auto r = inclusiveRange(first, last);

  // Trusting iota's implementation
  size_t expectedLength = iota(first, last).length + 1;
  size_t i = 0;
  do {
assert(r.length == expectedLength);
r.popFront();
--expectedLength;
  } while (!r.empty);
}

unittest {
  // Should provide the BidirectionalRange interface
  import std.range : retro;
  import std.algorithm : equal;

  auto r = inclusiveRange(1, 10);
  assert(!r.save.retro.equal(r.save));
  assert(r.save.retro.retro.equal(r.save));
}

void main() {
  import std.stdio;
  import std.range;

  writeln(inclusiveRange(1, 10));
  writeln(inclusiveRange(1, 10).retro);

  auto r = inclusiveRange(1, 11);
  while (true) {
writefln!"%s .. %s  length: %s"(r.front, r.back, r.length);
r.popFront();
if (r.empty) {
  break;
}
r.popBack();
if (r.empty) {
  break;
}
  }
}

Ali



Re: why there is a [] at the end of assocArray

2022-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 1/19/22 06:06, michaelbi wrote:

On Wednesday, 19 January 2022 at 13:21:32 UTC, Stanislav Blinov wrote:

On Wednesday, 19 January 2022 at 13:15:35 UTC, michaelbi wrote:

    foreach(line; > 
File("input.txt").byLine.map!(a=>a.idup).array.transposed)



so why there is a [] at the end of assocArray printed? thanks.


...because there's an empty line at the end of input.txt?


i got it, though i still don't know where the [] come from. i just add 
strip here: a=>a.idup.strip


Works for me on Linux. Perhaps there is an issue with Windows line endings?

In any case, the .strip above would not be eliminating empty lines; you 
need to filter them out e.g. with


  byLine.filter!(line => !line.empty)

Aside: Instead of copying the lines with .idup explicitly, there is 
.byLineCopy that already does that.


Ali


Re: how to print "111000" out into 0b111000

2022-01-19 Thread Brian Callahan via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 15:01:29 UTC, michaelbi wrote:

as captioned... thx.


```d
import std.stdio;
import std.conv;

void main()
{
writefln("0b%b", to!int("111000", 2));
}
```


Re: Function prototype overloading does not work ?

2022-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/22 3:47 AM, Enjoys Math wrote:

```
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

class Expr
{
public:
    void opBinary(string op)(string s) const
    {
   static if (op == "+")
   {
  Expr right = null;

  if (s == ".." || s == "..." || s == "")
  {
     right = new Dots();
  }

  if (right !is null)
     return new Op("+", [this, right]);
   }
    }

    override string toString() const
    {
   assert(0);
    }

    Expr sub(Expr x, Expr y)
    {
   if (this == x)
  return y;
   return this;
    }

    Expr sub(Expr x, ref Var y)
    {
   return sub(x, new VarExpr(y));
    }

    Expr sub(ref Var x, Expr y)
    {
   return sub(new VarExpr(x), y);
    }

    Expr sub(int x, Expr y)
    {
   return sub(ZZ(x), y);
    }

    Expr sub(Expr x, int y)
    {
   return sub(x, ZZ(y));
    }

    Expr sub(ref Var x, ref Var y)
    {
   return sub(new VarExpr(x), new VarExpr(y));
    }

    Expr sub(ref Var x, int y)
    {
   return sub(new VarExpr(x), ZZ(y));
    }

    Expr sub(int x, ref Var y)
    {
   return sub(ZZ(x), new VarExpr(y));
    }

    override bool opEquals(Object o) {
   return this is o;
    }
}
```
See all the overloads I had to make to sub in order to bypass identity 
assignment for classes.  I.e. Var can't be of type Expr.  Anyway, this 
approach is not working because code calling `Expr.sub(int, Var)` is not 
seeing the definitions.  It says no function matching those args, but 
clearly there are!




sub(int, ref Var) exists, but not sub(int, Var). Is your Var an lvalue?

Without more code context, this is hard to diagnose. Can you post the 
offending call?


-Steve


how to print "111000" out into 0b111000

2022-01-19 Thread michaelbi via Digitalmars-d-learn

as captioned... thx.


Re: why there is a [] at the end of assocArray

2022-01-19 Thread jfondren via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 14:06:45 UTC, michaelbi wrote:

i got it, though i still don't know where the [] come from.


$ rdmd --eval 'writeln("".array.strip.sort.group.assocArray)'
[]
$ rdmd --eval 
'writeln(typeid("".array.strip.sort.group.assocArray))'

uint[dchar]

It's what an empty AA looks like.


Re: why there is a [] at the end of assocArray

2022-01-19 Thread michaelbi via Digitalmars-d-learn
On Wednesday, 19 January 2022 at 13:21:32 UTC, Stanislav Blinov 
wrote:

On Wednesday, 19 January 2022 at 13:15:35 UTC, michaelbi wrote:

	foreach(line; > 
File("input.txt").byLine.map!(a=>a.idup).array.transposed)



so why there is a [] at the end of assocArray printed? thanks.


...because there's an empty line at the end of input.txt?


i got it, though i still don't know where the [] come from. i 
just add strip here: a=>a.idup.strip


Re: why there is a [] at the end of assocArray

2022-01-19 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 13:15:35 UTC, michaelbi wrote:

	foreach(line; > 
File("input.txt").byLine.map!(a=>a.idup).array.transposed)



so why there is a [] at the end of assocArray printed? thanks.


...because there's an empty line at the end of input.txt?


why there is a [] at the end of assocArray

2022-01-19 Thread michaelbi via Digitalmars-d-learn

input:
00100
0
10110
10111
10101
0
00111
11100
1
11001
00010
01010

code:
void main()
{
	foreach(line; 
File("input.txt").byLine.map!(a=>a.idup).array.transposed){

auto sortgroup = line.array.strip.sort.group.assocArray;
writeln(sortgroup);
}
}

output:
['1':7, '0':5]
['1':5, '0':7]
['1':8, '0':4]
['1':7, '0':5]
['1':5, '0':7]
[]

so why there is a [] at the end of assocArray printed? thanks.


Re: number ranges

2022-01-19 Thread Salih Dincer via Digitalmars-d-learn

On Tuesday, 18 January 2022 at 23:13:14 UTC, Ali Çehreli wrote:


But I like the following one better because
it is fast and I think it works correctly.


Is it okay to swap places instead of throwing an error? Let's 
also implement BidirectionalRange, if okay. This great struct 
will now run 4x4 like a Jeep. 


Moreover, the iota doesn't even care if define char type. And no 
throwing an error.


The real question to ask is:

"Does it reverse the result
in case ```a > b``` like we
did with foreach_reverse()"

Salih

```d
import std;

struct InclusiveRange(T) {
  T front, last;

  this(U)(in U front, in U last) {
this.front = front;
this.last = last;

if(empty) toogleFrontLast();
  }

  bool empty() {
return front > last;
  }

  void popFront() {
if(!empty) ++front;
  }

  T back() {
return last;
  }

  void popBack() {
if(!empty) --last;
  }

  void toogleFrontLast() {
auto temp = this.last;
this.last = this.front;
this.front = temp;
  }
}

auto inclusiveRange(T)(T first, T last) {
  return InclusiveRange!T(first, last);
}

enum a = 8; // ASCII 80: P
enum b = 7; // ASCII 70: F

alias type = char;
alias test = inclusiveRange;

void main() {
  string str; // for tests...
  auto io = iota!type(a * 10, b * 10);
   io.writeln("\n", typeof(io).stringof, "\n");

  str = to!string(io);
  assert(str == "[]"); // OMG, why?

  auto ir = test!type(a * 10, b * 10);
   ir.writeln("\n", typeof(ir).stringof, "\n");

  str = to!string(ir);
  assert(str == "FGHIJKLMNOP"); // Ok

  foreach_reverse(c; ir) str ~= c;
  assert(str == "FGHIJKLMNOPPONMLKJIHGF"); // Ok
}
```


Re: Improve a simple event handler

2022-01-19 Thread Hipreme via Digitalmars-d-learn

On Sunday, 16 January 2022 at 20:01:09 UTC, JN wrote:

On Saturday, 15 January 2022 at 23:15:16 UTC, JN wrote:


Is there some way I could improve this with some D features? 
My main gripes with it are:




Managed to dramatically simplify it to 10 lines of code with 
variadic templates.


```d
import std.stdio;

struct Event(T...)
{
void function(T)[] listeners;

void addListener(void function(T) handler)
{
listeners ~= handler;
}

void emit(T args)
{
foreach (listener; listeners)
{
listener(args);
}
}
}

void onResize(uint newWidth, uint newHeight)
{
writefln("Resized: %d %d", newWidth, newHeight);
}

void main()
{
Event!(uint, uint) windowResizeEvent;
windowResizeEvent.addListener();

windowResizeEvent.emit(1000, 2000);
}
```

I am very happy with this solution.



My advice is to make your listeners return a boolean. This 
boolean is used to basically stop propagating the event. And 
debugging it seems really hard to be honest, so, incrementing it 
a little, I would do:



```d

struct ListenerInfo
{
  string name;
  string file;
  uint line;
  string registeredAt;
}
struct Event(T...)
{
  bool function(T)[] listeners;
  ListenerInfo[] info;
  void addListener(bool function(T) handler, string name, string 
file = __FILE__, uint line = __LINE__, string registeredAt = 
__PRETTY_FUNCTION__)

  {
 listeners~= handler;
 info~= ListenerInfo(name, file, line, registeredAt);
  }

  void emit(T args)
  {
foreach(i, l; listeners)
{
  if(l(args))
  {
writeln(info[i]);
break;
  }
}
  }
}

```

You could even extend this concept further by making it return an 
enum value for actually removing the listener when executed, 
stopping propagation. Or you could have access to the listener 
info inside the arguments too.




Re: Debug symbols from libs not being linked on windows

2022-01-19 Thread Hipreme via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 02:31:31 UTC, Hipreme wrote:
I have separated my project in a bunch of modules to be 
compiled separated. But it seems I have lost my debugging power 
since then. I would like to know if there is any workaround 
beside not using it as a lib.


I'm using it from dub and it is has the debug options on them:
```
"buildOptions": [
"debugMode",
"debugInfo",
"debugInfoC"
],
```

And on every lib too.



I had some errors about "duplicate object file, linking without 
debug info", an error that really should not exist as D works in 
modules. But I have renamed the necessary modules for getting rid 
of that message.


After that, the problem was fixed by doing `dub clean 
--all-packages`, thanks rikki!







Re: Throw stack trace from program kill

2022-01-19 Thread Hipreme via Digitalmars-d-learn

On Sunday, 16 January 2022 at 18:03:53 UTC, Paul Backus wrote:

On Sunday, 16 January 2022 at 15:15:07 UTC, Hipreme wrote:
Is there some way to throw a stack trace when killing the 
program from the CTRL+C from the terminal?


It would help a lot into debugging occasional infinity loops


On POSIX, you can use the `sigaction` function to install a 
signal handler for `SIGINT`, the signal generated by CTRL+C. To 
terminate the program with a stack trace, simply have the 
signal handler `throw` an `Error`.


Here's an example program that demonstrates the technique:

```d
import core.sys.posix.signal;

extern(C) void handleCtrlC(int)
{
throw new Error("Killed by CTRL+C");
}

void main()
{
sigaction_t act = { sa_handler:  };
int errcode = sigaction(SIGINT, , null);

f(); // call some functions
}

void f() { g(); }

void g() { h(); }

void h()
{
while (1) {} // wait for ctrl+c
}

```

Make sure to compile with the `-g` option if you want your 
stack trace to have filenames and line numbers.


```d
import std.stdio;

version(Posix)
{
import core.sys.posix.signal;
extern(C) void handleCtrlC(int)
{
throw new Error("Killed by CTRL+C");
}

bool setupSignal()
{
sigaction_t act = {sa_handler: };
int errCode = sigaction(SIGINT, , null);
return errCode == 0;
}
}
else version(Windows)
{
import core.sys.windows.windef;
import core.sys.windows.wincon;
extern(Windows) BOOL handleCtrlC(DWORD dwType)
{
switch(dwType)
{
case CTRL_C_EVENT:
throw new Error("Killed by CTRL+C");
break;
case CTRL_BREAK_EVENT:
throw new Error("Killed by break");
break;
default:
throw new Error("Killed by unknown event");
break;
}
return TRUE;
}
bool setupSignal()
{
return 
SetConsoleCtrlHandler(cast(PHANDLER_ROUTINE), TRUE) 
== TRUE;

}
}
else{bool setupSignal(){return false;}}

void a(){b();}
void b(){c();}
void c(){for(;;){}}

void main(string[] args)
{
if(!setupSignal)
writeln("Could not setup signal, exiting.");
else
a();
}
```


This is my current solution. The problem is that on Windows, it 
actually has the stack trace:


```
0x76909A63 in CtrlRoutine 
  0x76BD6359 
in BaseThreadInitThunk
   0x76FF7B74 in 
RtlGetAppContainerNamedObjectPath 
0x76FF7B44 in 
RtlGetAppContainerNamedObjectPath

```

If I throw that error on the Ctrl, it actually shows a message 
box:


`The exception unknown software exception (0xe0441) occurred 
in the application at location: ...`


Maybe there is some specific formatting for throwing exceptions 
to Windows recognize it?


Re: Function prototype overloading does not work ?

2022-01-19 Thread vit via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 08:47:27 UTC, Enjoys Math wrote:

```
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

class Expr
{
public:
   void opBinary(string op)(string s) const
   {
  static if (op == "+")
  {
 Expr right = null;

 if (s == ".." || s == "..." || s == "")
 {
right = new Dots();
 }

 if (right !is null)
return new Op("+", [this, right]);
  }
   }

   override string toString() const
   {
  assert(0);
   }

   Expr sub(Expr x, Expr y)
   {
  if (this == x)
 return y;
  return this;
   }

   Expr sub(Expr x, ref Var y)
   {
  return sub(x, new VarExpr(y));
   }

   Expr sub(ref Var x, Expr y)
   {
  return sub(new VarExpr(x), y);
   }

   Expr sub(int x, Expr y)
   {
  return sub(ZZ(x), y);
   }

   Expr sub(Expr x, int y)
   {
  return sub(x, ZZ(y));
   }

   Expr sub(ref Var x, ref Var y)
   {
  return sub(new VarExpr(x), new VarExpr(y));
   }

   Expr sub(ref Var x, int y)
   {
  return sub(new VarExpr(x), ZZ(y));
   }

   Expr sub(int x, ref Var y)
   {
  return sub(ZZ(x), new VarExpr(y));
   }

   override bool opEquals(Object o) {
  return this is o;
   }
}
```
See all the overloads I had to make to sub in order to bypass 
identity assignment for classes.  I.e. Var can't be of type 
Expr.  Anyway, this approach is not working because code 
calling `Expr.sub(int, Var)` is not seeing the definitions.  It 
says no function matching those args, but clearly there are!


Try replacing methods sub with template:
```d
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

class Expr
{
public:
   void opBinary(string op)(string s) const;

   override string toString() const;

   Expr sub(Expr x, Expr y)
   {
  if (this == x)
 return y;
  return this;
   }

//template sub:
Expr sub(T, U)(auto ref T x, auto ref U y){

//transform parameter to Expr:
static Expr expr(E)(auto ref E e){
static if(is(E : Expr))
return e;
else static if(is(E : int))
return ZZ(e);
else static if(is(E : Var))
return new VarExpr(e);
else
static assert(0, "no impl " ~ E.stringof);
}

//call sub(Expr, Expr)
this.sub(expr(x), expr(y));

}

   override bool opEquals(Object o) ;
}
```


Re: Function prototype overloading does not work ?

2022-01-19 Thread Hipreme via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 08:47:27 UTC, Enjoys Math wrote:

```
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

class Expr
{
public:
   void opBinary(string op)(string s) const
   {
  static if (op == "+")
  {
 Expr right = null;

 if (s == ".." || s == "..." || s == "")
 {
right = new Dots();
 }

 if (right !is null)
return new Op("+", [this, right]);
  }
   }

   override string toString() const
   {
  assert(0);
   }

   Expr sub(Expr x, Expr y)
   {
  if (this == x)
 return y;
  return this;
   }

   Expr sub(Expr x, ref Var y)
   {
  return sub(x, new VarExpr(y));
   }

   Expr sub(ref Var x, Expr y)
   {
  return sub(new VarExpr(x), y);
   }

   Expr sub(int x, Expr y)
   {
  return sub(ZZ(x), y);
   }

   Expr sub(Expr x, int y)
   {
  return sub(x, ZZ(y));
   }

   Expr sub(ref Var x, ref Var y)
   {
  return sub(new VarExpr(x), new VarExpr(y));
   }

   Expr sub(ref Var x, int y)
   {
  return sub(new VarExpr(x), ZZ(y));
   }

   Expr sub(int x, ref Var y)
   {
  return sub(ZZ(x), new VarExpr(y));
   }

   override bool opEquals(Object o) {
  return this is o;
   }
}
```
See all the overloads I had to make to sub in order to bypass 
identity assignment for classes.  I.e. Var can't be of type 
Expr.  Anyway, this approach is not working because code 
calling `Expr.sub(int, Var)` is not seeing the definitions.  It 
says no function matching those args, but clearly there are!



Firstly, in my opinion, you should be using `auto ref` which will 
do the same thing as generating by reference and by value 
declarations. Or you could even use `in` as the compiler will 
optimize the call for passing it by reference.


Now, you could have some self contained example for we being able 
to test it




Function prototype overloading does not work ?

2022-01-19 Thread Enjoys Math via Digitalmars-d-learn

```
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

class Expr
{
public:
   void opBinary(string op)(string s) const
   {
  static if (op == "+")
  {
 Expr right = null;

 if (s == ".." || s == "..." || s == "")
 {
right = new Dots();
 }

 if (right !is null)
return new Op("+", [this, right]);
  }
   }

   override string toString() const
   {
  assert(0);
   }

   Expr sub(Expr x, Expr y)
   {
  if (this == x)
 return y;
  return this;
   }

   Expr sub(Expr x, ref Var y)
   {
  return sub(x, new VarExpr(y));
   }

   Expr sub(ref Var x, Expr y)
   {
  return sub(new VarExpr(x), y);
   }

   Expr sub(int x, Expr y)
   {
  return sub(ZZ(x), y);
   }

   Expr sub(Expr x, int y)
   {
  return sub(x, ZZ(y));
   }

   Expr sub(ref Var x, ref Var y)
   {
  return sub(new VarExpr(x), new VarExpr(y));
   }

   Expr sub(ref Var x, int y)
   {
  return sub(new VarExpr(x), ZZ(y));
   }

   Expr sub(int x, ref Var y)
   {
  return sub(ZZ(x), new VarExpr(y));
   }

   override bool opEquals(Object o) {
  return this is o;
   }
}
```
See all the overloads I had to make to sub in order to bypass 
identity assignment for classes.  I.e. Var can't be of type Expr. 
 Anyway, this approach is not working because code calling 
`Expr.sub(int, Var)` is not seeing the definitions.  It says no 
function matching those args, but clearly there are!