Re: use of struct vs class

2020-03-07 Thread mark via Digitalmars-d-learn

Steve, thank you once again. Now it compiles & runs!

I now create my tree like this:

auto debs = new RedBlackTree!(Deb, (a, b) => a.name < b.name);

(I feel that the rbtree docs are inadequate regarding creating 
new empty trees, so have submitted a bug report:

https://issues.dlang.org/show_bug.cgi?id=20646 )

The other problem I had was that the Deb I created on the stack 
had its own internal rbtree that was always null.


To address this I changed tags in the Deb struct to this:

auto tags = new RedBlackTree!string;

so it always creates a new empty tree. And I renamed clear to 
reset and now do this:


void reset() {
name = "";
...
tags = new RedBlackTree!string;
...
}

I assume that I can safely rely on the GC to clean up for me.

So now I think I can safely use the pattern (1., repeat 2.1, ... 
) described earlier: certainly it builds and runs.


Next I'll have to try really populating the Debs including their 
tag trees and populating the debs tree of Debs structs.


Thank you.





Re: use of struct vs class

2020-03-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/7/20 8:22 AM, mark wrote:
0x55701ef0 in 
_D3std9container6rbtree__T12RedBlackTreeTAyaVQea5_61203c2062Vbi0ZQBn5emptyMFNaNbNdNiNfZb 
(this=0x0)
     at 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/../import/std/container/rbtree.d:967 


967    return _end.left is null;
(gdb) bt
#0  0x55701ef0 in 
_D3std9container6rbtree__T12RedBlackTreeTAyaVQea5_61203c2062Vbi0ZQBn5emptyMFNaNbNdNiNfZb 
(this=0x0)


RedBlackTree is a class. Make sure you allocate it. The above shows 
"this = 0x0".


I saw a few other "this = 0x0" items, but perhaps that's OK for your 
code, I don't know what those types are.


-Steve


Re: use of struct vs class

2020-03-07 Thread drug via Digitalmars-d-learn

07.03.2020 15:58, Steven Schveighoffer пишет:


Hm... I'd say:

1. Don't use a pointer for the element. Just use the struct directly. 
Using a pointer is bad because it's now going to compare pointers, and 
not the element data. Not only that, but RBNodes are stored as 
heap-allocated structs, so you are wasting a lot of memory by allocating 
another heap allocated thing to get stored inside there.


You can use predicate to solve the issue like you suggest below. But I'm 
totally missed that RBNodes are heap-allocated, thanks!


2. RedBlackTree allows you to identify the relationship that you 
consider unique by providing a "less" function. Instead of instrumenting 
your Deb type, which might affect other usages, just do:


RedBlackTree!(Deb, (a, b) => a.name < b.name)
 > No need to add opCmp and opEquals (if that doesn't make sense in other
contexts).

-Steve





Re: use of struct vs class

2020-03-07 Thread mark via Digitalmars-d-learn
I've now gone back to using structs direct without pointers but 
I'm still doing something wrong.


struct Deb {
string name;
...
RedBlackTree!string tags;

bool valid() { return !(name.empty || description.empty); }

void clear() { name = ""; ...; tags.clear; }
}

RedBlackTree!(Deb, (a, b) => a.name < b.name) debs;

Deb deb;
auto file = File(filename);
foreach(line; file.byLine) {
line = strip(line);
if (line.empty) {
if (deb.valid)
debs.insert(deb); // XXX
else // report incomplete
deb.clear;
continue;
}
...
}
if (deb.valid)
debs.insert(deb);

This compiles & crashes with "Program exited with code -11".

What I'm trying to do but clearly don't understand is this:

1. create a struct
repeat:
 2.1. populate the struct
 2.2. copy the struct into an rbtree // XXX
 2.3. clear the original struct
 2.4. loop

At XXX does a copy take place? I thought it did with structs?

Anyway, here's the backtrace:

$ gdb DebFind
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
...
Reading symbols from DebFind...done.
(gdb) run
Starting program: /home/mark/app/d/debfind/DebFind
[Thread debugging using libthread_db enabled]
Using host libthread_db library 
"/lib/x86_64-linux-gnu/libthread_db.so.1".

[New Thread 0x76e02700 (LWP 2366)]
...

Thread 1 "DebFind" received signal SIGSEGV, Segmentation fault.
0x55701ef0 in 
_D3std9container6rbtree__T12RedBlackTreeTAyaVQea5_61203c2062Vbi0ZQBn5emptyMFNaNbNdNiNfZb (this=0x0)
at 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/../import/std/container/rbtree.d:967

967 return _end.left is null;
(gdb) bt
#0  0x55701ef0 in 
_D3std9container6rbtree__T12RedBlackTreeTAyaVQea5_61203c2062Vbi0ZQBn5emptyMFNaNbNdNiNfZb (this=0x0)
at 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/../import/std/container/rbtree.d:967
#1  0x55701a11 in 
qtrac.debfind.model.Model.readPackageFile(immutable(char)[]) 
(this=0x0, filename=...) at model.d:66
warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


warning: (Internal error: pc 0x5591b820 in read in psymtab, 
but not in symtab.)


warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


#2  0x55701671 in 
qtrac.debfind.model.Model.initialize(int) (this=0x0, 
maxDebNamesForWord=100) at model.d:31
warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


#3  0x557045b0 in 
_D5qtrac7debfind9appwindow9AppWindow6__ctorMFC3gtk11ApplicationQnZCQCnQCkQCfQBy (this=0x77ece630, application=0x77ed1360) at appwindow.d:31
#4  0x55722819 in 
_D5qtrac7debfind3app4mainFAAyaZ__T12__dgliteral2TC3gio11ApplicationQnZQBkMFQBaZv (GioApplication=0x77ed1360) at app.d:16
#5  0x5575be54 in 
_D7gobject8DClosureQj__T17d_closure_marshalTDFC3gio11ApplicationQnZvZQBtUPSQCv1c5types8GClosurePSQDrQwQw6GValuekQrPvQcZv (closure=0x55c37690, return_value=0x0, n_param_values=1, param_values=0x77ef46e0, invocation_hint=0x7fffd710 "\b", marshal_data=0x0) at DClosure.d:122
#6  0x7419410d in g_closure_invoke () at 
/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#7  0x741a705e in  () at 
/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#8  0x741af715 in g_signal_emit_valist () at 
/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#9  0x741b012f in g_signal_emit () at 
/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


#10 0x7fffee148b95 in  () at 
/usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


#11 0x7fffee148da6 in g_application_run () at 
/usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


#12 0x5591b875 in warning: (Internal error: pc 
0x5591b874 in read in psymtab, but not in symtab.)


_D3gio11ApplicationQn3runMFAAyaZiwarning: (Internal error: pc 
0x5591b874 in read in psymtab, but not in symtab.)


warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


 (warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


this=0x77ed1360, warning: (Internal error: pc 0x5591b874 
in read in psymtab, but not in symtab.)


argv=...)warning: (Internal error: pc 0x5591b874 in read in 
psymtab, but not in symtab.)


 at Application.dwarning: (Internal error: pc 0x5591b874 in 
read in psymtab, but not in symtab.)


warning: (Internal error: pc 0x5591b874 in read in psymtab, 
but not in symtab.)


:931
#13 0x55722760 in D main (args=...) at app.d:18


And thanks for helping!


Re: use of struct vs class

2020-03-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/7/20 5:58 AM, mark wrote:

change #1:

     if (line.empty) {
     if (deb != null && deb.valid)
     debs.insert(deb);
     else // report incomplete
     deb = null;
     continue;
     }
     if (deb == null)
     deb = new Deb;

change #2: gets rid of most errors:

     bool opEquals(const Deb* other) const @safe pure nothrow {

     int opCmp(ref const Deb* other) const {

Just changed to pointers & moved to a separate file.

So now I just have one error in line 12 of model.d:

RedBlackTree!Deb* debs; // name-ordered list of deb packages LINE 12


Performing "debug" build using 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 for x86_64.

gtk-d:gtkd 3.9.0: target for configuration "library" is up to date.
debfind ~master: building configuration "application"...
src/model.d(12,9): Error: template instance 
std.container.rbtree.RedBlackTree!(Deb) does not match template 
declaration RedBlackTree(T, alias less = "a < b", bool allowDuplicates = 
false)

   with T = Deb
   must satisfy the following constraint:
    is(typeof(binaryFun!less(T.init, T.init)))
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 failed with exit code 1.



Hm... I'd say:

1. Don't use a pointer for the element. Just use the struct directly. 
Using a pointer is bad because it's now going to compare pointers, and 
not the element data. Not only that, but RBNodes are stored as 
heap-allocated structs, so you are wasting a lot of memory by allocating 
another heap allocated thing to get stored inside there.


2. RedBlackTree allows you to identify the relationship that you 
consider unique by providing a "less" function. Instead of instrumenting 
your Deb type, which might affect other usages, just do:


RedBlackTree!(Deb, (a, b) => a.name < b.name)

No need to add opCmp and opEquals (if that doesn't make sense in other 
contexts).


-Steve


Re: use of struct vs class

2020-03-07 Thread drug via Digitalmars-d-learn

07.03.2020 13:58, mark пишет:

change #1:

     if (line.empty) {
     if (deb != null && deb.valid)
     debs.insert(deb);
     else // report incomplete
     deb = null;
     continue;
     }
     if (deb == null)
     deb = new Deb;

change #2: gets rid of most errors:

     bool opEquals(const Deb* other) const @safe pure nothrow {

     int opCmp(ref const Deb* other) const {

Just changed to pointers & moved to a separate file.

So now I just have one error in line 12 of model.d:

RedBlackTree!Deb* debs; // name-ordered list of deb packages LINE 12


Performing "debug" build using 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 for x86_64.

gtk-d:gtkd 3.9.0: target for configuration "library" is up to date.
debfind ~master: building configuration "application"...
src/model.d(12,9): Error: template instance 
std.container.rbtree.RedBlackTree!(Deb) does not match template 
declaration RedBlackTree(T, alias less = "a < b", bool allowDuplicates = 
false)

   with T = Deb
   must satisfy the following constraint:
    is(typeof(binaryFun!less(T.init, T.init)))
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 failed with exit code 1.



try
```
RedBlackTree!(Deb*) debs;
```


Re: use of struct vs class

2020-03-07 Thread mark via Digitalmars-d-learn

change #1:

if (line.empty) {
if (deb != null && deb.valid)
debs.insert(deb);
else // report incomplete
deb = null;
continue;
}
if (deb == null)
deb = new Deb;

change #2: gets rid of most errors:

bool opEquals(const Deb* other) const @safe pure nothrow {

int opCmp(ref const Deb* other) const {

Just changed to pointers & moved to a separate file.

So now I just have one error in line 12 of model.d:

RedBlackTree!Deb* debs; // name-ordered list of deb packages LINE 
12



Performing "debug" build using 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 for x86_64.
gtk-d:gtkd 3.9.0: target for configuration "library" is up to 
date.

debfind ~master: building configuration "application"...
src/model.d(12,9): Error: template instance 
std.container.rbtree.RedBlackTree!(Deb) does not match template 
declaration RedBlackTree(T, alias less = "a < b", bool 
allowDuplicates = false)

  with T = Deb
  must satisfy the following constraint:
   is(typeof(binaryFun!less(T.init, T.init)))
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 failed with exit 
code 1.




Re: use of struct vs class

2020-03-07 Thread mark via Digitalmars-d-learn

Instead of deb.clear I'm now doing deb = null;


Re: use of struct vs class

2020-03-07 Thread mark via Digitalmars-d-learn

On Saturday, 7 March 2020 at 10:30:06 UTC, drug wrote:

07.03.2020 13:20, mark пишет:

I have this struct (with details omitted
[ snip ]
Should Deb be a class rather than a struct?


Do you consider using pointers in AA:
```
Deb*[string] debForName;
```


I've done some changes including using Deb* as you suggested:

struct Deb {
string name;
...
RedBlackTree!string tags;

bool valid() { return !(name.empty || description.empty); }

size_t toHash() const @safe nothrow {
return typeid(name).getHash(&name); // names are unique
}

bool opEquals(const Deb other) const @safe pure nothrow {
return name == other.name; // names are unique
}

int opCmp(ref const Deb other) const {
return cmp(name, other.name); // names are unique
}
}

Which I now want to store in:

RedBlackTree!Deb* debs; // name-ordered list of deb packages

And now I'm populating like this:

Deb* deb;
auto file = File(filename);
foreach(line; file.byLine) {
line = strip(line);
if (line.empty) {
if (deb != null && deb.valid) {
debs.insert(deb);
deb.clear;
}
// else report incomplete package
continue;
}
if (deb == null)
deb = new Deb;
...
}
if (deb != null && deb.valid)
debs.insert(deb);

But it crashes with:

Performing "debug" build using 
/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/ldc2 for x86_64.
gtk-d:gtkd 3.9.0: target for configuration "library" is up to 
date.

debfind ~master: building configuration "application"...
src/model.d(96,36): Error: template 
std.container.rbtree.RedBlackTree!(Deb, "a < b", 
false).RedBlackTree.stableInsert cannot deduce function from 
argument types !()(Deb*), candidates are:

/home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/../import/std/container/rbtree.d(1256,12):
stableInsert(Stuff)(Stuff stuff)
  with Stuff = Deb*
  must satisfy the following constraint:
   isImplicitlyConvertible!(Stuff, Elem)
...




Re: use of struct vs class

2020-03-07 Thread drug via Digitalmars-d-learn

07.03.2020 13:20, mark пишет:

I have this struct (with details omitted
[ snip ]
Should Deb be a class rather than a struct?


Do you consider using pointers in AA:
```
Deb*[string] debForName;
```


use of struct vs class

2020-03-07 Thread mark via Digitalmars-d-learn

I have this struct (with details omitted ... for brevity):

struct Deb {
string name;
...
RedBlackTree!string tags;

void clear() { name = ""; ...; tags.clear; }

bool valid() { return !(name.empty || description.empty); }
}

I plan to store >65K of these (with potential for growth to 
>250K) in an AA:


Deb[string] debForName;

I plan to populate debForName by reading data files (actually 
Debian Packages files) like this:


Deb deb;
auto file = File(filename):
foreach(line; file.byLine) {
if (line.empty) {
if (deb.valid) // end of package
debForName[deb.name] = deb; // XXX
// else report incomplete package
deb.clear;
continue;
}
... // populate the deb
}
if (deb.valid)
debForName[deb.name] = deb;

I'm assuming that line XXX will copy the Deb including the tree 
(which as usual I'm using as a set -- I really miss a set class 
in D!). Will this work (I'll find out myself next week when I get 
further, but D experts can likely tell from the above).


Should Deb be a class rather than a struct?