how can i mixin a function as struct or class member function
for example: function void a(int i) { writeln(i); } auto JSFunction(alias F)() if(isSomeFunction!F) { class S { public ReturnType!F dg(ParameterTypeTuple!F) { mixin(F.body) // what should i do ??? } } } thank you
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote: Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class? IMO it doesn't need to be. However, it's worth saying that range semantics aren't a great fit for parsers - at least that's been my experience. Parsers need to be able to "synchronize" to recover from syntax errors, which does not fit into the range API very well. You can probably fit it in somewhere in popFront or front or empty, as your implementation permits, but I find it's just easier to forego the range interface and implement whatever primitives you need; *then* you can add a range interface over top that models the output of the parser as a range of expressions, or whatever you want.
Re: Should a parser type be a struct or class?
Oh an also https://github.com/dlang/dmd/pull/9899
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 14:32:09 UTC, Adam D. Ruppe wrote: On Wednesday, 17 June 2020 at 14:24:01 UTC, Stefan Koch wrote: Parser in dmd does even inherit from Lexer. why would a parser ever inherit from a lexer? So you can write nextToken() instead of lexer.nextToken()
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote: Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class? You have the example of libdparse that shows that using a class can be a good idea [1] [2]. For DCD, the parser overrides a few thing because otherwise completion does not work properly or has scope issues. But TBH there's not many reasons to use a class otherwise. [1] https://github.com/dlang-community/dsymbol/blob/master/src/dsymbol/conversion/package.d#L102 [2] https://github.com/dlang-community/dsymbol/blob/master/src/dsymbol/conversion/package.d#L138
Re: Should a parser type be a struct or class?
On Wed, Jun 17, 2020 at 02:32:09PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: > On Wednesday, 17 June 2020 at 14:24:01 UTC, Stefan Koch wrote: > > Parser in dmd does even inherit from Lexer. > > why would a parser ever inherit from a lexer? Because, unlike a regular parser-driven compiler, dmd is a lexer-driven one. :-D T -- The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a. -- Wouter Verhelst
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 14:24:01 UTC, Stefan Koch wrote: Parser in dmd does even inherit from Lexer. why would a parser ever inherit from a lexer?
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote: Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class? I would say a struct. Parser in dmd does even inherit from Lexer. It seems to be a quirky design. Especially for multi-threaded parsing you might want to have more control over memory layout than classes usually give you.
Re: Should a parser type be a struct or class?
On Wed, Jun 17, 2020 at 11:50:27AM +, Per Nordlöw via Digitalmars-d-learn wrote: > Should a range-compliant aggregate type realizing a parser be encoded > as a struct or class? Preferably a struct IMO, but see below. > In dmd `Lexer` and `Parser` are both classes. Probably for historical reasons. > In general how should I reason about whether an aggregate type should > be encoded as a struct or class? 1) Does it need runtime polymorphism? If it does, use a class. If not, probably a struct. 2) Does it make more sense as a by-value type, or a by-reference type? In several of my projects, for example, I've had aggregate types start out as structs (because of (1)), but eventually rewritten as (final) classes because I started finding myself using `ref` or `&` everywhere to get by-reference semantics. My rule-of-thumb is basically adopted from TDPL: a struct as a "glorified int" with by-value semantics, a class is a more traditional OO object. If my aggregate behaves like a glorified int, then a struct is a good choice. If it behaves more like a traditional OO encapsulated type, then a class is probably the right answer. T -- Many open minds should be closed for repairs. -- K5 user
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote: Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class? What's a range-compliant aggregate type? Ranges are typically views of someone else's data; an owner of the data woulnd't store mutable iterators, and won't be a range. For that reason also, ranges are structs, as most of them are thin wrappers over a set of iterators with an interface to mutate them. If you *really* need runtime polymorphism as provided by the language - use a class. Otherwise - use a struct. It's pretty straightforward. Even then, in some cases one can realize their own runtime polymorphism without classes (look at e.g. Atila Neves' 'tardy' library). It's very easy to implement a lexer as an input range: it'd just be a pointer into a buffer plus some additional iteration data (like line/column position, for example). I.e. a struct. Making it a struct also allows to make it into a forward range, instead of input range, which is useful if you need lookahead: struct TokenStream { this(SourceBuffer source) { this.cursor = source.text.ptr; advance(this); } bool empty() const { return token.type == TokenType.eof; } ref front() return scope const { return token; } void popFront() { switch (token.type) { default: advance(this); break; case TokenType.eof: break; case TokenType.error: token.type = TokenType.eof; token.lexSpan = LexicalSpan(token.lexSpan.end, token.lexSpan.end); break; } } TokenStream save() const { return this; } private: const(char)* cursor; Location location; Token token; } , where `advance` is implemented as a module private function that actually parses source into next token. DMD's Lexer/Parser aren't ranges. They're ourobori.
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote: Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class? The heuristic I use is 'do I need polymorphism?' If no, it's a struct. Another thing that may be worth considering is reference semantics. The latter is easy to do with a struct, while polymorphism is generally a class-only thing (but check out Tardy, which Atila Neves recently posted in the Announce group). I would say I basically never use classes in D - pointers and arrays give me all the reference semantics I need, and polymorphism I almost never need. -- Simen
Should a parser type be a struct or class?
Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class?
Re: Get unknown symbol (struct, method, class) tagged with User Defined Attributes
On 2020-05-12 06:02, Steven Schveighoffer wrote: If you want a list of ALL symbols that have the UDA in the application, that would require some form of runtime reflection (like Java). D has very limited support for runtime reflection. In D, you would use some form of registration to tell the system about your symbols. I think it's possible to implement the `RTInfo` template in `object.d`. But that requires a custom druntime. `RTInfo` is a template that is instantiated once for each type in the program. -- /Jacob Carlborg
Re: Get unknown symbol (struct, method, class) tagged with User Defined Attributes
On Tuesday, 12 May 2020 at 04:02:18 UTC, Steven Schveighoffer wrote: In the case of serialization/deserialization, you give an instance of a type to serialize or deserialize. Then the library can search the symbols inside that type to see if any has the UDA you are looking for. In the Rust example, there is a line of code: let p: Person = serde_json::from_str(data)?; I'm assuming that this conversion is detected and figured out (i.e. this is how serde "finds" the type desired). For D, it would look something like: auto p = serde_json.from_str!Person(data); If you want a list of ALL symbols that have the UDA in the application, that would require some form of runtime reflection (like Java). D has very limited support for runtime reflection. In D, you would use some form of registration to tell the system about your symbols. -Steve Thanks for the feedback. I've got a better idea of what is and isn't possible now. I'll see about looking at one or two D JSON libraries to see how they approach things. It should help shed some more light on the subject.
Re: Get unknown symbol (struct, method, class) tagged with User Defined Attributes
On 5/11/20 11:30 PM, Doug wrote: On Tuesday, 12 May 2020 at 02:53:53 UTC, Adam D. Ruppe wrote: see std.traits.getSymbolsByUDA Thanks for the link. I did see that one. But that function searches within known symbols. My use case if for a library that's used outside of my application. In that case, I wouldn't know which symbol a library applies an annotation to. This is why I asked for how to get a list of unknown symbols from a known UDA. To use a REST frame work as an example, I would supply a @GET annotation and a user would apply that annotation to a handler method. I wouldn't know the method or module in advanced so I wouldn't know which symbol to pass to "getSymbolsByUDA" of any of it's sibling functions. I'm curious to see what I'd be able to do if this is possible. So the idea is that you know the parent symbol. In the case of serialization/deserialization, you give an instance of a type to serialize or deserialize. Then the library can search the symbols inside that type to see if any has the UDA you are looking for. In the Rust example, there is a line of code: let p: Person = serde_json::from_str(data)?; I'm assuming that this conversion is detected and figured out (i.e. this is how serde "finds" the type desired). For D, it would look something like: auto p = serde_json.from_str!Person(data); If you want a list of ALL symbols that have the UDA in the application, that would require some form of runtime reflection (like Java). D has very limited support for runtime reflection. In D, you would use some form of registration to tell the system about your symbols. -Steve
Re: Get unknown symbol (struct, method, class) tagged with User Defined Attributes
On Tuesday, 12 May 2020 at 02:53:53 UTC, Adam D. Ruppe wrote: see std.traits.getSymbolsByUDA Thanks for the link. I did see that one. But that function searches within known symbols. My use case if for a library that's used outside of my application. In that case, I wouldn't know which symbol a library applies an annotation to. This is why I asked for how to get a list of unknown symbols from a known UDA. To use a REST frame work as an example, I would supply a @GET annotation and a user would apply that annotation to a handler method. I wouldn't know the method or module in advanced so I wouldn't know which symbol to pass to "getSymbolsByUDA" of any of it's sibling functions. I'm curious to see what I'd be able to do if this is possible.
Re: Get unknown symbol (struct, method, class) tagged with User Defined Attributes
On Tuesday, 12 May 2020 at 02:51:39 UTC, Doug wrote: So far I've only seen a way to get unknown UDAs from known symbols but not how to get unknown symbols from UDAs. Is there any documentation for how to get a list of symbols annotated with a specific UDA? see std.traits.getSymbolsByUDA http://dpldocs.info/experimental-docs/std.traits.getSymbolsByUDA.html there's some caveats, like it only searches one particular parent symbol for its children (that's because the way this works is you reflect through children checking each symbol child's uda list to see if it is present) but it basically works for many things at least contained per-module. you can pass each module you care about in though to generate a more full list
Get unknown symbol (struct, method, class) tagged with User Defined Attributes
I've seen a lot of examples of how to get a list of User Defined Attributes from a known symbol but I haven't seen any for how to get a list of symbols when only the UDA is known. The use case is the same as seen in Rust with Serde[1]. Library users annotate a struct to mark it for serialization. In Java and Spring, you can mark a method with @Secured to add authorization to an endpoint[2]. In both of these cases, you have no idea which symbol the UDA will be applied to. So far I've only seen a way to get unknown UDAs from known symbols but not how to get unknown symbols from UDAs. Is there any documentation for how to get a list of symbols annotated with a specific UDA? 1: Serde: https://github.com/serde-rs/json 2: Spring: https://www.baeldung.com/spring-security-method-security
Re: use of struct vs class
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
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
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
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
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
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
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
Instead of deb.clear I'm now doing deb = null;
Re: use of struct vs class
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(); // 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
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
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?
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 09:43:25 UTC, Rnd wrote: These similarities and differences should be highlighted in documentation etc since many new users have at least some knowledge of C/C++ and understanding will be easier. Perhaps this will help: https://dlang.org/articles/ctod.html
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 08:54:12 UTC, Jonathan M Davis wrote: structs in D are basically the same as C++ classes that don't have inheritance and can be put on the stack or the heap, and classes in D are akin to C++ classes that use inheritance and are always put on the heap and used via pointers. D classes are similar to Java classes in that respect. - Jonathan M Davis Also struct in D seem to be very similar to classes in C except lack of inheritance. These similarities and differences should be highlighted in documentation etc since many new users have at least some knowledge of C/C++ and understanding will be easier.
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 08:50:46 UTC, Mike Parker wrote: On Monday, 3 June 2019 at 08:47:41 UTC, Mike Parker wrote: If yes, when should one use 'new'? Whenever you need to allocate something from the GC heap. In my experience, it's rare to need it with value types in D. I tend to use it primarily with classes and arrays. Ali's book has an example using a struct-based linked list in the chapter on pointers: https://forum.dlang.org/thread/rkmcvxftykhsvxofp...@forum.dlang.org Wrong link. It's at: http://ddili.org/ders/d.en/pointers.html
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 08:47:41 UTC, Mike Parker wrote: If yes, when should one use 'new'? Whenever you need to allocate something from the GC heap. In my experience, it's rare to need it with value types in D. I tend to use it primarily with classes and arrays. Ali's book has an example using a struct-based linked list in the chapter on pointers: https://forum.dlang.org/thread/rkmcvxftykhsvxofp...@forum.dlang.org
Re: What is difference between struct and class?
On Monday, June 3, 2019 1:13:44 AM MDT Rnd via Digitalmars-d-learn wrote: > On Monday, 3 June 2019 at 06:01:15 UTC, Jonathan M Davis wrote: > > On Sunday, June 2, 2019 9:40:43 PM MDT Rnd via > > > > Digitalmars-d-learn wrote: > >> On Monday, > > > > http://ddili.org/ders/d.en/index.html > > > > If you want to know more about structs and classes > > specifically, then you can go straight to the sections on them, > > but you're going to understand a lot of things better if you > > just read through the book. > > > > - Jonathan M Davis > > I know 'new' is not needed to create instances of structs but can > one use 'new'? > > If yes, when should one use 'new'? Yes, you can use new with structs, just like you can use it with ints or floats or almost any type. It puts the struct on the heap instead of the stack. When that makes sense depends on when you need to have a struct on the heap instead of the stack. It's basically the same as why you'd want to put a class without inheritance on the heap in C++. structs in D are basically the same as C++ classes that don't have inheritance and can be put on the stack or the heap, and classes in D are akin to C++ classes that use inheritance and are always put on the heap and used via pointers. D classes are similar to Java classes in that respect. - Jonathan M Davis
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 07:13:44 UTC, Rnd wrote: I know 'new' is not needed to create instances of structs but can one use 'new'? Yes. It can be used with any value type to allocate a block of memory on the GC heap and return a pointer to that memory: struct Foo { ... } Foo* f = new Foo; int* i = new int; If yes, when should one use 'new'? Whenever you need to allocate something from the GC heap. In my experience, it's rare to need it with value types in D. I tend to use it primarily with classes and arrays.
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 06:01:15 UTC, Jonathan M Davis wrote: On Sunday, June 2, 2019 9:40:43 PM MDT Rnd via Digitalmars-d-learn wrote: On Monday, http://ddili.org/ders/d.en/index.html If you want to know more about structs and classes specifically, then you can go straight to the sections on them, but you're going to understand a lot of things better if you just read through the book. - Jonathan M Davis I know 'new' is not needed to create instances of structs but can one use 'new'? If yes, when should one use 'new'?
Re: What is difference between struct and class?
On Sunday, June 2, 2019 9:40:43 PM MDT Rnd via Digitalmars-d-learn wrote: > On Monday, 3 June 2019 at 00:47:27 UTC, Adam D. Ruppe wrote: > > On Monday, 3 June 2019 at 00:17:08 UTC, Rnd wrote: > >> What additional features do classes offer in D? > > > > Classes support built-in runtime polymorphism through > > inheritance. structs don't. > > > > As a result of this, classes are a little bit heavier > > resource-wise and are semantically always object references. > > I am not clear if structs can have constructors (this) and > whether they can be multiple? Also can data be made private and > getters and setters used to access them? Yes structs can have constructors (but no default constructor - the default value of a struct is its init value, which is defined by the values that the struct's members are directly initialized with), and structs can have all of the various functions that a class can have. The can also use private, public, and package just like classes can (but not protected, since structs have no inheritance). Basically, structs go wherever they're declared and don't have inheritance, whereas classes are always reference types and have inheritance. In general, besides that, their abilities are pretty much the same, though there are some differences that stem from the fact that classes are always reference types, whereas structs aren't. I'd advise reading http://ddili.org/ders/d.en/index.html If you want to know more about structs and classes specifically, then you can go straight to the sections on them, but you're going to understand a lot of things better if you just read through the book. - Jonathan M Davis
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 00:47:27 UTC, Adam D. Ruppe wrote: On Monday, 3 June 2019 at 00:17:08 UTC, Rnd wrote: What additional features do classes offer in D? Classes support built-in runtime polymorphism through inheritance. structs don't. As a result of this, classes are a little bit heavier resource-wise and are semantically always object references. I am not clear if structs can have constructors (this) and whether they can be multiple? Also can data be made private and getters and setters used to access them?
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 00:17:08 UTC, Rnd wrote: What additional features do classes offer in D? Classes support built-in runtime polymorphism through inheritance. structs don't. As a result of this, classes are a little bit heavier resource-wise and are semantically always object references.
What is difference between struct and class?
I see that struct can have data as well as member functions and instances can be created. So they sound like classes only. What additional features do classes offer in D?
Re: static immutable and lambdas inside struct or class. Is that bug or not?
On Sunday, 14 August 2016 at 15:53:21 UTC, ag0aep6g wrote: On 08/14/2016 04:27 PM, Uranuz wrote: [...] Looks like a compiler bug, since it works without the struct: import std.algorithm: map; import std.array: array; import std.typecons: tuple; immutable aaa = [ tuple("1", "one"), tuple("2", "two"), tuple("3", "three") ]; immutable bbb = aaa.map!( a => a[0] ).array; And that's essentially the same thing. It has already been filed: https://issues.dlang.org/show_bug.cgi?id=15908 For a workaround, it works when you explicitly state the type of the parameter: struct A { import std.algorithm: map; import std.array: array; import std.typecons: tuple, Tuple; static immutable aaa = [ tuple("1", "one"), tuple("2", "two"), tuple("3", "three") ]; alias Tup = Tuple!(string, string); static immutable bbb = aaa.map!( (Tup a) => a[0] ).array; } OK. I just declared alias for predicate outside struct to workaround. Maybe compiler trying to get context when attemting to infer arguments for some reason, but fails. Or something else...
Re: static immutable and lambdas inside struct or class. Is that bug or not?
On 08/14/2016 04:27 PM, Uranuz wrote: Greatings! I need help with these lines bellow. I don't understand why it doesn't compile. Is it bug somewhere in Phobos or compiler? Or just I wrote smth wrong? //- struct A { import std.algorithm: map; import std.array: array; import std.typecons: tuple; static immutable aaa = [ tuple("1", "one"), tuple("2", "two"), tuple("3", "three") ]; static immutable bbb = aaa.map!( a => a[0] ).array; } void main() { A a = A(); } //- Compilation output: /opt/compilers/dmd2/include/std/algorithm/iteration.d(455): Error: this.__lambda6 has no value You could test it here: https://dpaste.dzfl.pl/67a8cda8f2a8 Looks like a compiler bug, since it works without the struct: import std.algorithm: map; import std.array: array; import std.typecons: tuple; immutable aaa = [ tuple("1", "one"), tuple("2", "two"), tuple("3", "three") ]; immutable bbb = aaa.map!( a => a[0] ).array; And that's essentially the same thing. It has already been filed: https://issues.dlang.org/show_bug.cgi?id=15908 For a workaround, it works when you explicitly state the type of the parameter: struct A { import std.algorithm: map; import std.array: array; import std.typecons: tuple, Tuple; static immutable aaa = [ tuple("1", "one"), tuple("2", "two"), tuple("3", "three") ]; alias Tup = Tuple!(string, string); static immutable bbb = aaa.map!( (Tup a) => a[0] ).array; }
static immutable and lambdas inside struct or class. Is that bug or not?
Greatings! I need help with these lines bellow. I don't understand why it doesn't compile. Is it bug somewhere in Phobos or compiler? Or just I wrote smth wrong? //- struct A { import std.algorithm: map; import std.array: array; import std.typecons: tuple; static immutable aaa = [ tuple("1", "one"), tuple("2", "two"), tuple("3", "three") ]; static immutable bbb = aaa.map!( a => a[0] ).array; } void main() { A a = A(); } //- Compilation output: /opt/compilers/dmd2/include/std/algorithm/iteration.d(455): Error: this.__lambda6 has no value You could test it here: https://dpaste.dzfl.pl/67a8cda8f2a8
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 17:22:40 UTC, NX wrote: I wonder if the followings are compiler bugs: class stuff_class { byte[1024*1024*16] arr; // Error: index 16777216 overflow for static array } struct stuff { byte[1024*1024*16] arr; // Error: index 16777216 overflow for static array } My project has just stopped for this reason, I was trying to hack into another process memory with something similar to this: stuff data; ReadProcessMemory(Proc, (void*)0xA970F4, data, stuff.sizeof, null); Target program is written in C++ and because of this limitation I'm not able to write equivalent code and here I'm stuck. There a limit for static array size. This limits is exactly 16MB so 1024*1024*16. Remove one element: byte[1024*1024*16-1] arr;
Re: Static arrays inside struct and class - bug?
Typo: *scenario
Static arrays inside struct and class - bug?
I wonder if the followings are compiler bugs: class stuff_class { byte[1024*1024*16] arr; // Error: index 16777216 overflow for static array } struct stuff { byte[1024*1024*16] arr; // Error: index 16777216 overflow for static array } My project has just stopped for this reason, I was trying to hack into another process memory with something similar to this: stuff data; ReadProcessMemory(Proc, (void*)0xA970F4, data, stuff.sizeof, null); Target program is written in C++ and because of this limitation I'm not able to write equivalent code and here I'm stuck.
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 17:29:54 UTC, Adam D. Ruppe wrote: On Saturday, 1 August 2015 at 17:22:40 UTC, NX wrote: I wonder if the followings are compiler bugs: No, it is by design, the idea is to keep static arrays smallish so null references will be caught by the processor. (An overly large static array could allow indexing it through a null pointer to potentially reach another object.) The easiest workaround is to just dynamically allocate such huge arrays: byte[] arr = new byte[](1024*1024*16); ReadProcessMemory(Proc, 0xdeadbeef, arr.ptr, arr.length, null); The arr.ptr and arr.length are the key arguments there. Sorry, I can't see _the_ point in that. I understand that could be a problem if it was a global array but this scenery is completely wrong in my view. I'm already going to dynamically allocate it and my problem is actually a lot complex than what I showed there, I not even allowed to do this: struct stuff { byte[1024*1024*16] arr; // Error: index 16777216 overflow for static array } //... stuff* data = new stuff; ReadProcessMemory(Proc, (void*)0xA970F4, data, stuff.sizeof, null); Here (https://gist.github.com/NightmareX1337/6408287d7823c8a4ba20) is the real issue if anyone want to see the real-world problem with long lines of code
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 17:22:40 UTC, NX wrote: I wonder if the followings are compiler bugs: No, it is by design, the idea is to keep static arrays smallish so null references will be caught by the processor. (An overly large static array could allow indexing it through a null pointer to potentially reach another object.) The easiest workaround is to just dynamically allocate such huge arrays: byte[] arr = new byte[](1024*1024*16); ReadProcessMemory(Proc, 0xdeadbeef, arr.ptr, arr.length, null); The arr.ptr and arr.length are the key arguments there.
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 18:07:51 UTC, NX wrote: Sorry, I can't see _the_ point in that. Yeah, especially since you can jsut break up the array and get the same effect anyway... so like if you don't want to dynamically allocate the memory, you could also try: byte[1024*1024*8] arr1; byte[1024*1024*8] arr2; If they are right next to each other they will still be continuous in memory and then you work around the limit.
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 18:47:00 UTC, Daniel Kozak wrote: Still same problem, You can`t allocate more then 16M on stack. Use dynamic allocation I don't think new MyStruct allocates on stack, actually allocating ~16MB on stack will immediatelly crash the program which is not the case with NewExpression.
Re: Static arrays inside struct and class - bug?
V Sat, 01 Aug 2015 19:21:36 + NX via Digitalmars-d-learn digitalmars-d-learn@puremagic.com napsáno: On Saturday, 1 August 2015 at 18:50:09 UTC, Daniel Kozak wrote: No you don't. You still use static allocation for array Can clarify why does that happen and I still suspect it's a static allocation it would increase output exe if it was really that static..? No it would not increase output exe. Problem is with definition: type[size] val; // static declaration so compilere check max 16M. But you are right, in your case it could be improved and such declaration could work. because: S { byte[16*1024*1024*1024] arr; } void main() { auto s = new S(); if (s is null) { // error cannont allocate enought memory } } but: void main() { byte[16*1024*1024*1024] arr; // impossible to check if is allocated } Maybe you can open an enhancment on issues.dlang.org
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 18:07:51 UTC, NX wrote: On Saturday, 1 August 2015 at 17:29:54 UTC, Adam D. Ruppe wrote: Sorry, I can't see _the_ point in that. I understand that could be a problem if it was a global array but this scenery is completely wrong in my view. I'm already going to dynamically allocate it No you don't. You still use static allocation for array
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 18:50:09 UTC, Daniel Kozak wrote: No you don't. You still use static allocation for array Can clarify why does that happen and I still suspect it's a static allocation it would increase output exe if it was really that static..?
Re: Static arrays inside struct and class - bug?
V Sat, 01 Aug 2015 19:16:16 + NX via Digitalmars-d-learn digitalmars-d-learn@puremagic.com napsáno: On Saturday, 1 August 2015 at 18:47:00 UTC, Daniel Kozak wrote: Still same problem, You can`t allocate more then 16M on stack. Use dynamic allocation I don't think new MyStruct allocates on stack, actually allocating ~16MB on stack will immediatelly crash the program which is not the case with NewExpression. My fault It is not on stack, but still it is a static allocation
Re: Static arrays inside struct and class - bug?
On Saturday, 1 August 2015 at 19:33:26 UTC, Daniel Kozak wrote: My fault It is not on stack, but still it is a static allocation I think you're misusing static allocation and static declaration for each other.
Re: Static arrays inside struct and class - bug?
V Sat, 01 Aug 2015 18:07:50 + NX via Digitalmars-d-learn digitalmars-d-learn@puremagic.com napsáno: On Saturday, 1 August 2015 at 17:29:54 UTC, Adam D. Ruppe wrote: On Saturday, 1 August 2015 at 17:22:40 UTC, NX wrote: I wonder if the followings are compiler bugs: No, it is by design, the idea is to keep static arrays smallish so null references will be caught by the processor. (An overly large static array could allow indexing it through a null pointer to potentially reach another object.) The easiest workaround is to just dynamically allocate such huge arrays: byte[] arr = new byte[](1024*1024*16); ReadProcessMemory(Proc, 0xdeadbeef, arr.ptr, arr.length, null); The arr.ptr and arr.length are the key arguments there. Sorry, I can't see _the_ point in that. I understand that could be a problem if it was a global array but this scenery is completely wrong in my view. I'm already going to dynamically allocate it and my problem is actually a lot complex than what I showed there, I not even allowed to do this: struct stuff { byte[1024*1024*16] arr; // Error: index 16777216 overflow for static array } //... stuff* data = new stuff; ReadProcessMemory(Proc, (void*)0xA970F4, data, stuff.sizeof, null); Here (https://gist.github.com/NightmareX1337/6408287d7823c8a4ba20) is the real issue if anyone want to see the real-world problem with long lines of code Still same problem, You can`t allocate more then 16M on stack. Use dynamic allocation
Re: Struct vs. Class
On Fri, 26 Jun 2015 11:11:15 + Chris via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I have still some classes lying around in my code. As threading is becoming more and more of an issue, classes and OOP in general turn out to be a nuisance. It's not so hard to turn the classes into structs, a lot of classes are in fact singletons (yes, I've been kinda fading out classes for a while now). My question is now, what do I have to keep in mind if I turn a cached class into a cached struct, i.e. initProgram() { auto myClass = new AwesomeDoEverything.instance(); // lives for the rest of the program, is a singleton } // ... myClass.call(input); initProgram() { auto myStruct = AwesomeDoEverything(); // lives for the rest of the program } // ... myStruct.call(input); // Can live in different threads without reinitializing it. Or is there a way I can make a singleton class thread-able? I cannot afford to re-initialize certain classes / structs because I don't wanna hit the file system every time I do so. bad link: http://dlang.org/phobos/std_concurrency.html#.initOnce
Re: Struct vs. Class
On Fri, 26 Jun 2015 11:11:15 + Chris via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I have still some classes lying around in my code. As threading is becoming more and more of an issue, classes and OOP in general turn out to be a nuisance. It's not so hard to turn the classes into structs, a lot of classes are in fact singletons (yes, I've been kinda fading out classes for a while now). My question is now, what do I have to keep in mind if I turn a cached class into a cached struct, i.e. initProgram() { auto myClass = new AwesomeDoEverything.instance(); // lives for the rest of the program, is a singleton } // ... myClass.call(input); initProgram() { auto myStruct = AwesomeDoEverything(); // lives for the rest of the program } // ... myStruct.call(input); // Can live in different threads without reinitializing it. Or is there a way I can make a singleton class thread-able? I cannot afford to re-initialize certain classes / structs because I don't wanna hit the file system every time I do so. http://dlang.org/library/std/concurrency/init_once.html
Struct vs. Class
I have still some classes lying around in my code. As threading is becoming more and more of an issue, classes and OOP in general turn out to be a nuisance. It's not so hard to turn the classes into structs, a lot of classes are in fact singletons (yes, I've been kinda fading out classes for a while now). My question is now, what do I have to keep in mind if I turn a cached class into a cached struct, i.e. initProgram() { auto myClass = new AwesomeDoEverything.instance(); // lives for the rest of the program, is a singleton } // ... myClass.call(input); initProgram() { auto myStruct = AwesomeDoEverything(); // lives for the rest of the program } // ... myStruct.call(input); // Can live in different threads without reinitializing it. Or is there a way I can make a singleton class thread-able? I cannot afford to re-initialize certain classes / structs because I don't wanna hit the file system every time I do so.
Re: Struct vs. Class
On Friday, 26 June 2015 at 11:28:38 UTC, Daniel Kozák wrote: On Fri, 26 Jun 2015 11:11:15 + Chris via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I have still some classes lying around in my code. As threading is becoming more and more of an issue, classes and OOP in general turn out to be a nuisance. It's not so hard to turn the classes into structs, a lot of classes are in fact singletons (yes, I've been kinda fading out classes for a while now). My question is now, what do I have to keep in mind if I turn a cached class into a cached struct, i.e. initProgram() { auto myClass = new AwesomeDoEverything.instance(); // lives for the rest of the program, is a singleton } // ... myClass.call(input); initProgram() { auto myStruct = AwesomeDoEverything(); // lives for the rest of the program } // ... myStruct.call(input); // Can live in different threads without reinitializing it. Or is there a way I can make a singleton class thread-able? I cannot afford to re-initialize certain classes / structs because I don't wanna hit the file system every time I do so. bad link: http://dlang.org/phobos/std_concurrency.html#.initOnce Thanks a million! This might do the trick and my classes can live happily ever after :-)
struct or class
I come from languages that don't offer structs, I have this json load function that has to keep some data and intuitively I've written a struct, I've read about the differences, heap vs stack, value vs reference, but know I think i am overthinking it. Is this decent: bool loadFromFile (string path) { auto data = readText(path); JSONValue parsed = parseJSON(data); struct AtlasSpriteData { SDL_Rect clipRectangle; int xOffset; int yOffset; } AtlasSpriteData[string] dict; foreach( string name, value; parsed[frames] ){ SDL_Rect clipRectangle; auto spriteSourceSize = value[spriteSourceSize]; clipRectangle.x = to!int(frame[x].toString()); clipRectangle.y = to!int(frame[y].toString()); clipRectangle.w = to!int(frame[w].toString()); clipRectangle.h = to!int(frame[h].toString()); int xOffset = to!int(spriteSourceSize[x].toString()); int yOffset = to!int(spriteSourceSize[y].toString()); auto data = AtlasSpriteData(clipRectangle, xOffset, yOffset); dict[name] = data; } Or should I use a class for that AtlasSpriteData? reading about it I get the impression everytime I'll look up data from that dictionary data will get copied ?
Re: struct or class
On 24/08/2014 11:56 p.m., nikki wrote: I come from languages that don't offer structs, I have this json load function that has to keep some data and intuitively I've written a struct, I've read about the differences, heap vs stack, value vs reference, but know I think i am overthinking it. Here's a simple way of working it out. If you're using arrays of a type, use classes. If you're storing lots of data inside it, classes. If you need inheritance, classes. If you have simple data for returning/argument passing then struct. Basically, small, short lived allocations stack. Long lived, large allocations, classes. At least that's my opinion.
Re: struct or class
On Sunday, 24 August 2014 at 11:56:44 UTC, nikki wrote: I come from languages that don't offer structs, I have this json load function that has to keep some data and intuitively I've written a struct, I've read about the differences, heap vs stack, value vs reference, but know I think i am overthinking it. Is this decent: bool loadFromFile (string path) { auto data = readText(path); JSONValue parsed = parseJSON(data); struct AtlasSpriteData { SDL_Rect clipRectangle; int xOffset; int yOffset; } AtlasSpriteData[string] dict; foreach( string name, value; parsed[frames] ){ SDL_Rect clipRectangle; auto spriteSourceSize = value[spriteSourceSize]; clipRectangle.x = to!int(frame[x].toString()); clipRectangle.y = to!int(frame[y].toString()); clipRectangle.w = to!int(frame[w].toString()); clipRectangle.h = to!int(frame[h].toString()); int xOffset = to!int(spriteSourceSize[x].toString()); int yOffset = to!int(spriteSourceSize[y].toString()); auto data = AtlasSpriteData(clipRectangle, xOffset, yOffset); dict[name] = data; } Or should I use a class for that AtlasSpriteData? reading about it I get the impression everytime I'll look up data from that dictionary data will get copied ? Your struct instance will occupy only 24 bytes. It's ok even if you will copy it. I would avoid heap allocation in this case. Also what is 'frame' variable? I don't see local declaration of it. Or you just forgot to replace 'value' with 'frame'. Does not JSONValue.integer fit in this case instead of to!int(JSONValue.toString()) ? Reading does not perform copy if you access struct directly as dict[name].some_field. Copying is performed only if you pass struct by value or assign it to variable.
Re: struct or class
On Sun, 24 Aug 2014 11:56:42 + nikki via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Or should I use a class for that AtlasSpriteData? reading about it I get the impression everytime I'll look up data from that dictionary data will get copied ? this will copy: auto sd = dict[0]; this will copy: foreach (sd; dict) { ... } this will not: const *sd = dict[0]; this will not: foreach (ref sd; dict) { ... } hope you got the idea. signature.asc Description: PGP signature
Re: struct or class
On Sun, 24 Aug 2014 11:56:42 + nikki via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Or should I use a class for that AtlasSpriteData? reading about it I get the impression everytime I'll look up data from that dictionary data will get copied ? p.s. this will not copy: auto sd = mysprite00 in dict; 'sd' is of type 'AtlasSpriteData*' here. signature.asc Description: PGP signature
Re: struct or class
On Sunday, 24 August 2014 at 11:56:44 UTC, nikki wrote: I come from languages that don't offer structs, I have this json load function that has to keep some data and intuitively I've written a struct, I've read about the differences, heap vs stack, value vs reference, but know I think i am overthinking it. Is this decent: bool loadFromFile (string path) { auto data = readText(path); JSONValue parsed = parseJSON(data); struct AtlasSpriteData { SDL_Rect clipRectangle; int xOffset; int yOffset; } AtlasSpriteData[string] dict; foreach( string name, value; parsed[frames] ){ SDL_Rect clipRectangle; auto spriteSourceSize = value[spriteSourceSize]; clipRectangle.x = to!int(frame[x].toString()); clipRectangle.y = to!int(frame[y].toString()); clipRectangle.w = to!int(frame[w].toString()); clipRectangle.h = to!int(frame[h].toString()); int xOffset = to!int(spriteSourceSize[x].toString()); int yOffset = to!int(spriteSourceSize[y].toString()); auto data = AtlasSpriteData(clipRectangle, xOffset, yOffset); dict[name] = data; } Or should I use a class for that AtlasSpriteData? reading about it I get the impression everytime I'll look up data from that dictionary data will get copied ? In this case class makes sense (assuming AtlasSpriteData has few instances that will be shared around a lot). But you could also use a pointer to a struct, especially if you manually allocate it and want to avoid the GC. Also, you can read data from the associative array by reference (basic example, no error checking): ref AtlasSpriteData spriteData(string name) { return dict[name]; }
Re: struct in class access
On Sunday, 9 December 2012 at 07:39:29 UTC, js.mdnq wrote: On Sunday, 9 December 2012 at 07:24:57 UTC, Jonathan M Davis wrote: On Sunday, December 09, 2012 07:54:25 js.mdnq wrote: Why can't a struct inside a class access the members of that class without a this pointer? It would seem natural to me that a nested struct should probably be special in that it is really just a special container to reduce clutter in the class. Without a this pointer, there are no class members to access, because they have to be associated with a specific instance of the class unless they're static. Non-static, nested structs have access to their enclosing scope, but then you can't create them separate from the enclosing class. However, if you declare a nested class to be static, it has no access to the class' members and is not associated with a specific instance of the class. It's just that it's declared inside the class instead of outside of it. - Jonathan M Davis NO It does have a this pointer!! If the sub-struct is a true sub struct then it is inline inside the memory of the class! That is, any member inside a struct can easily be gotten from the pointer to the class(object) as one just has to add a simple(and static) offset. That is why nested struct inside a class actually does not have a context pointer -its fields addresses are calculated as offsets from class this pointer, not from struct this pointer. If the struct is only used inside the class then there should be no problem. Problems comes when nested struct is created inside a function without creating a class. It makes no sense to have a struct inside a class behave exactly as that outside as it offers no benefit to do so(or maybe it does, but very little). Hence, we can redefine the way structs behave inside classes to make them more useful. Perhaps the situation can be improved. In any case, take this example: class A { public: string Name; struct B { public: int x; alias x this; void func(A _a) { writeln(_a.Name, x, y); }} B x; B y; } ... A a; What is the address of A? Meaning a, it is null. What is the address of x inside A? (i.e., the struct inside A?) x does not exists Is it not a simple static offset from the address of A? i.e., knowing the address of a lets us know the address of x. Knowing the address of x also lets us know the address of a! (Same goes for y) Yes, it is a CT-known offset which varies from one class to another. Note, you can insert nested struct into another class. This is why a nested struct(using my semantics) contains the this pointer! (because it is a simple offset from the this pointer which can be computed at compile time)! That's why nested struct does not have this pointer - it is POD structure. http://dpaste.dzfl.pl/76e8ec0a
Re: struct in class access
On Sunday, 9 December 2012 at 08:56:00 UTC, Maxim Fomin wrote: On Sunday, 9 December 2012 at 07:39:29 UTC, js.mdnq wrote: On Sunday, 9 December 2012 at 07:24:57 UTC, Jonathan M Davis wrote: On Sunday, December 09, 2012 07:54:25 js.mdnq wrote: Why can't a struct inside a class access the members of that class without a this pointer? It would seem natural to me that a nested struct should probably be special in that it is really just a special container to reduce clutter in the class. Without a this pointer, there are no class members to access, because they have to be associated with a specific instance of the class unless they're static. Non-static, nested structs have access to their enclosing scope, but then you can't create them separate from the enclosing class. However, if you declare a nested class to be static, it has no access to the class' members and is not associated with a specific instance of the class. It's just that it's declared inside the class instead of outside of it. - Jonathan M Davis NO It does have a this pointer!! If the sub-struct is a true sub struct then it is inline inside the memory of the class! That is, any member inside a struct can easily be gotten from the pointer to the class(object) as one just has to add a simple(and static) offset. That is why nested struct inside a class actually does not have a context pointer -its fields addresses are calculated as offsets from class this pointer, not from struct this pointer. If the struct is only used inside the class then there should be no problem. Problems comes when nested struct is created inside a function without creating a class. It makes no sense to have a struct inside a class behave exactly as that outside as it offers no benefit to do so(or maybe it does, but very little). Hence, we can redefine the way structs behave inside classes to make them more useful. Perhaps the situation can be improved. In any case, take this example: class A { public: string Name; struct B { public: int x; alias x this; void func(A _a) { writeln(_a.Name, x, y); }} B x; B y; } ... A a; What is the address of A? Meaning a, it is null. What is the address of x inside A? (i.e., the struct inside A?) x does not exists Is it not a simple static offset from the address of A? i.e., knowing the address of a lets us know the address of x. Knowing the address of x also lets us know the address of a! (Same goes for y) Yes, it is a CT-known offset which varies from one class to another. Note, you can insert nested struct into another class. This is why a nested struct(using my semantics) contains the this pointer! (because it is a simple offset from the this pointer which can be computed at compile time)! That's why nested struct does not have this pointer - it is POD structure. http://dpaste.dzfl.pl/76e8ec0a Yes, this is basically what I mean. structs to have addresses as everything does in memory. But structs are created inline. I do not know what you mean x does not exist and the address of a. x does exist(in the sense of any other variable) and a does have an address. You say That is why nested struct inside a class actually does not have a context pointer -its fields addresses are calculated as offsets from class this pointer, not from struct this pointer. But if this is true, and a difference between nested structs, then there should be no issue implementing what I am talking about. What I am talking about would require the struct to only be used inside the class as a class field. (as the struct is just encapsulating members of the class and not meant to stand on it's own, because, as you said, it would need a this pointer associated with it) With my method, I should easily be able calculate, from a relative offset, the members of the class and use them. This means that the compiler should be able to do it for me. It then means that nested structs are not just structs stuck in a class for who knows what reason but actually signify that they are specially related to the class. e.g., class A { public: string Name; struct B { int x; void func(ref A tthis, int ofs) { byte *ptr = cast(byte*)tthis; ptr += ofs; writeln(*(cast(string*)(ptr))); } this(int y) { x = y; } } B b; this() { Name = test; b = B(3); } } A a = new A(); a.b.func(a, 8); prints test as expected. B.func acts just like a member of A in that it takes a this pointer just like any other member of A. It could be moved outside of the struct into A. Semantically there is little difference between using func inside B or inside A EXCEPT that we have to provide the static offsets and this ptr manually. If the compiler did it for us we
Re: struct in class access
On Sunday, 9 December 2012 at 09:06:28 UTC, Maxim Fomin wrote: On Sunday, 9 December 2012 at 06:54:33 UTC, js.mdnq wrote: Why can't a struct inside a class access the members of that class without a this pointer? It would seem natural to me that a nested struct should probably be special in that it is really just a special container to reduce clutter in the class. Your problem have obvious and simple workaround http://dpaste.dzfl.pl/701affe8 Nope, sorry, as I said, I do not want to keep 4 to 8 bytes FOR NO REASON! It doesn't have to be done that way and it is not a work around. It is simply a waste of space.
struct in class access
Why can't a struct inside a class access the members of that class without a this pointer? It would seem natural to me that a nested struct should probably be special in that it is really just a special container to reduce clutter in the class. class a { string v; struct b { void fun() { writeln(v); } } b bb; } should be semantically equivalent to class a { string v; void bb.fun() { writeln(v); } } (and struct b does not have to include a this pointer since it is passed down) I'm in need of using structs to wrap opAssign so I can override for each variable(instead of a special method for each field in the class, which adds clutter and prevents using `=` properly). But I also want to access the class container's members. (and without having to enlarge the struct) It seems to me that the compiler should not have any difficult treating a struct method as a class method(passing the this ptr to it) but operating on struct's data. What's the difference between class a { int x; } and class a { struct b { alias _x this; int _x; } b x; } ? (and if be is made to be used inside the class only then it seems as if it's just basically no different than using the class alone except for some simplification(has it's own op's that one unfortunately can't keep distinct from the class align since they would overlap(although it would be nice). e.g., class a { string Name; void opAssign(T q) { }; // classes opAssign //{{ Essentially a struct here int x; void opAssign_x(T q) { writeln(Name); }; // Somehow overrides = for x. ('structs' opAssign) //}} } and class a { string Name; void opAssign(T q) { }; struct b { alias _x this; int _x; void opAssign(T q) { writeln(Name); }; } // Unfortunately we can't access Name b x; } i.e., it would seem to me that the only difference in the method opAssign of the struct is the offsets of the member variables is different(one referenced to the start of the struct and the first references them to start of the class. Therefor we shouldn't have any issues having properties from both the *true* nested struct and directly inlining it. i.e., we should be able to access outer members(the functionality when we inline the struct into the class) AND have multiple opAssign's(or any ops) per class that can be specified for any field(which is the functionality we get when we use the struct). Essentially what it boils down to is that nested structs do contain a this pointer to the parent class, so why can't we use it? (it's just some offset difference between the struct and class) I do realize that nested structs are not special in the current implementation AFAIK which to me, is a waste as they should be special. In any case, is there some other way to get the same behavior in D? One might say why don't I use classes as it solves the problem directly BUT there is a ton of wasted overhead for simply wrapping values. I would use template mixin's but the opAssigns would clash AFAIK. The struct encapsulation lets me get the correct opAssign behavior which is what I need but prevent me from accessing the outer class members which I should be able to do.
Re: struct in class access
On Sunday, December 09, 2012 07:54:25 js.mdnq wrote: Why can't a struct inside a class access the members of that class without a this pointer? It would seem natural to me that a nested struct should probably be special in that it is really just a special container to reduce clutter in the class. Without a this pointer, there are no class members to access, because they have to be associated with a specific instance of the class unless they're static. Non-static, nested structs have access to their enclosing scope, but then you can't create them separate from the enclosing class. However, if you declare a nested class to be static, it has no access to the class' members and is not associated with a specific instance of the class. It's just that it's declared inside the class instead of outside of it. - Jonathan M Davis
Re: struct in class access
On Sunday, 9 December 2012 at 07:24:57 UTC, Jonathan M Davis wrote: On Sunday, December 09, 2012 07:54:25 js.mdnq wrote: Why can't a struct inside a class access the members of that class without a this pointer? It would seem natural to me that a nested struct should probably be special in that it is really just a special container to reduce clutter in the class. Without a this pointer, there are no class members to access, because they have to be associated with a specific instance of the class unless they're static. Non-static, nested structs have access to their enclosing scope, but then you can't create them separate from the enclosing class. However, if you declare a nested class to be static, it has no access to the class' members and is not associated with a specific instance of the class. It's just that it's declared inside the class instead of outside of it. - Jonathan M Davis NO It does have a this pointer!! If the sub-struct is a true sub struct then it is inline inside the memory of the class! That is, any member inside a struct can easily be gotten from the pointer to the class(object) as one just has to add a simple(and static) offset. If the struct is only used inside the class then there should be no problem. If you look at the two examples I gave between a class and a struct inside a class, there is NO difference except for syntax! (excluding the way D does it already). I'm not trying to define how D does it, but how D should do it(assuming there is no blatant logic errors that makes it impossible). It makes no sense to have a struct inside a class behave exactly as that outside as it offers no benefit to do so(or maybe it does, but very little). Hence, we can redefine the way structs behave inside classes to make them more useful. In fact, maybe a struct is not the best way to do this but it requires very little modification. In any case, take this example: class A { public: string Name; struct B { public: int x; alias x this; void func(A _a) { writeln(_a.Name, x, y); }} B x; B y; } ... A a; What is the address of A? What is the address of x inside A? (i.e., the struct inside A?) Is it not a simple static offset from the address of A? i.e., knowing the address of a lets us know the address of x. Knowing the address of x also lets us know the address of a! (Same goes for y) This is why a nested struct(using my semantics) contains the this pointer! (because it is a simple offset from the this pointer which can be computed at compile time)! NOW!! In this case, a nested struct is simply making an encapsulation of class data but effectively is equivalent to having the data inside the class. (but allows us to avoid collisions between overrides in the class and the struct, which is why I think it will be more useful to have such behavior than the current(since the current seems to offer nothing useful). (
Re: struct in class access
... A a; What is the address of A? What is the address of x inside A? (i.e., the struct inside A?) I of course, mean a, which is why it's nice to have the ability to make an edit so I don't have to waste a post and/or someone else bloat the thread with A is a class, not an object, go learn how to program!.
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 18:00:42 UTC, Roman D. Boiko wrote: On Monday, 14 May 2012 at 17:37:02 UTC, Dmitry Olshansky wrote: But hopefully you get the idea. See something simillar in std.regex, though pointer in there also serves for intrusive linked-list. Thanks, most likely I'll go your way. If you don't mind doing some lite informational reading, read up on 'lex and yacc'. ISBN: 1-56592-000-7; Hope I got that right. I'm not telling you to use C (or the other tools mind you), but it does go into handling tokens of multiple types as well as managing them using pointers and unions. A good portion of that can carry over for your lexer and project.
Re: struct vs class for a simple token in my d lexer
On Tuesday, 15 May 2012 at 06:17:31 UTC, Era Scarecrow wrote: On Monday, 14 May 2012 at 18:00:42 UTC, Roman D. Boiko wrote: On Monday, 14 May 2012 at 17:37:02 UTC, Dmitry Olshansky wrote: But hopefully you get the idea. See something simillar in std.regex, though pointer in there also serves for intrusive linked-list. Thanks, most likely I'll go your way. If you don't mind doing some lite informational reading, read up on 'lex and yacc'. ISBN: 1-56592-000-7; Hope I got that right. I'm not telling you to use C (or the other tools mind you), but it does go into handling tokens of multiple types as well as managing them using pointers and unions. A good portion of that can carry over for your lexer and project. I've got flex bison edition (ISBN: 0596155972), will check there, thanks :)
Re: struct vs class for a simple token in my d lexer
On Tuesday, 15 May 2012 at 06:17:31 UTC, Era Scarecrow wrote: If you don't mind doing some lite informational reading, read up on 'lex and yacc'. ISBN: 1-56592-000-7; Hope I got that right. I'm not telling you to use C (or the other tools mind you), but it does go into handling tokens of multiple types as well as managing them using pointers and unions. A good portion of that can carry over for your lexer and project. Looks like I can introduce several lex/flex concepts in my lexer, thank you! I've created a task for myself to do this investigation: https://github.com/roman-d-boiko/dct/issues/42
Re: struct vs class for a simple token in my d lexer
On 05/14/12 17:10, Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks If you have to ask such a question, then the answer doesn't matter. Having said that, and w/o looking at the code, just based on the info in this thread - a few thoughts, which may or may not be helpful: - Use an array of pointers to struct tokens. IOW 'Token*[] tokens;'. Same use-syntax. Much less large continuous allocations. One indirection per token lookup, but that's no worse than using classes, but w/o the class overhead. - Don't let yourself be talked into adding unnecessary bloat, like storing location inside Tokens. If calculating it on demand turns out to be costly you can always store the location in a separate array (your array-of-structs scheme would make the lookup trivial, array-of-*-structs would make this slightly more complex, but if the info really is rarely needed, then it doesn't matter) - You can compress the string, if the 16 bytes is too much. Limiting the source unit size and max token length to 4G should be acceptable; then just have struct TokenStr { uint off, len; auto get(){return source[off..off+len];} etc which will reduce the memory footprint, while adding very little overhead. It's not like these strings will be used repeatedly. Don't forget to keep a reference to 'source' around, so that it isn't collected by the GC. (I'd even go for a 24:8 split, then you probably need to handle string literals longer then 255 bytes specially, but it's likely worth it. If somebody produces a 16M+ D source module he deserves the build failure. ;) ) I'm assuming the Token structs don't need destructors. artur
struct vs class for a simple token in my d lexer
(Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 15:10:25 UTC, Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks struct Token { TokenType type; string content; // type may as well be template parameter Area loc; // basically: ((x1, y1), (x2, y2)) } That's how my Token look like. The 2 or 3 times every token get's copied isn't worth a heap allocation with small type like this.
Re: struct vs class for a simple token in my d lexer
Quoting your post in another thread: On Monday, 14 May 2012 at 15:10:25 UTC, Roman D. Boiko wrote: Making it a class would give several benefits: * allow not to worry about allocating a big array of tokens. E.g., on 64-bit OS the largest module in Phobos (IIRC, the std.datetime) consumes 13.5MB in an array of almost 500K tokens. It would require 4 times smaller chunk of contiguous memory if it was an array of class objects, because each would consume only 8 bytes instead of 32. You'll still have count the space the tokens claim on the heap. So it's basically the 500k tokens plus 500k references. I'm not sure, why you would need such a big array of tokens, though. Aren't they produced by the lexer to be directly consumed and discarded by the parser? * allow subclassing, for example, for storing strongly typed literal values; this flexibility could also facilitate future extensibility (but it's difficult to predict which kind of extension may be needed) If performance matters, why would you subclass and risk a virtual method call for something as basic as tokens? * there would be no need to copy data from tokens into AST, passing an object would be enough (again, copy 8 instead of 32 bytes); the same applies to passing into methods - no need to pass by ref to minimise overhead I'm using string to store source content in tokens. Because of the way string in D works, there is no need for data copies. These considerations are mostly about performance. I think there is also some impact on design, but couldn't find anything significant (given that currently I see a token as merely a datastructure without associated behavior). IMO token are value types.
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 15:44:54 UTC, Tobias Pankrath wrote: On Monday, 14 May 2012 at 15:10:25 UTC, Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks struct Token { TokenType type; string content; // type may as well be template parameter Area loc; // basically: ((x1, y1), (x2, y2)) } That's how my Token look like. The 2 or 3 times every token get's copied isn't worth a heap allocation with small type like this. Yes, except that the array of tokens for big files requires a lot of **continuous** space (13.5M for std.datetime, up to 2M for a few others in phobos druntime). The array of references would 4 times less. Out of memory usually happens when the system cannot find a big enough chunck of memory, not when there is no available memory. On the contrary, I think that 10-20M on rare cases is not too much. Why I use the array I'll describe in the next post.
Re: struct vs class for a simple token in my d lexer
On Monday, May 14, 2012 17:10:23 Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks For the question in general, there are primarily 2 questions to consider: 1. Do you need inheritance/polymorphism? 2. Do you need a value type or a reference type? If you need inheritance/polymorphism, you have to use classes, because structs don't have inheritance. If you want a value type, you have to use structs, because classes are reference types. If you want a reference type, then you can use either a class or a struct, but it's easier with classes, because classes are always reference types, whereas structs are naturally value types, so it can take more work to make them reference types depending on what its member variables are. One other thing to consider is deterministic destruction. The only way to get deterministic destruction is to have a struct on the stack. Value types will naturally get that, but if you want a reference type with determinstic destruction, then you're probably going to have to use a ref-counted struct. In the vast majority of cases, that should be enough to decide whether you need a class or a struct. The main case that it doesn't is the case where you want a reference type and don't necessarily want a class, and that decision can get complicated. In the case of a token in a lexer, I would definitely expect that to be a value type, which means using a struct. - Jonathan M Davis
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 15:53:34 UTC, Tobias Pankrath wrote: Quoting your post in another thread: On Monday, 14 May 2012 at 15:10:25 UTC, Roman D. Boiko wrote: Making it a class would give several benefits: * allow not to worry about allocating a big array of tokens. E.g., on 64-bit OS the largest module in Phobos (IIRC, the std.datetime) consumes 13.5MB in an array of almost 500K tokens. It would require 4 times smaller chunk of contiguous memory if it was an array of class objects, because each would consume only 8 bytes instead of 32. You'll still have count the space the tokens claim on the heap. So it's basically the 500k tokens plus 500k references. I'm not sure, why you would need such a big array of tokens, though. Aren't they produced by the lexer to be directly consumed and discarded by the parser? I use sorted array of tokens for efficient 0(log N) lookup by its index (the first code unit of token). (Since tokens are created in increasing order of start indices, no further sorting is needed.) Lookup is used for two purposes: * find the token corresponding to location of cursor (e.g., for auto-complete) * combined with 0(log M) lookup in the ordered array of first line code unit indices, calculate the Location (line number and column number) for start / end of a token on demand (they are not pre-calculated because not used frequently); this approach also makes it easy to calculate Location either taking into account special token sequences (#line 3 ab/c.d), or ignoring them. * allow subclassing, for example, for storing strongly typed literal values; this flexibility could also facilitate future extensibility (but it's difficult to predict which kind of extension may be needed) If performance matters, why would you subclass and risk a virtual method call for something as basic as tokens? Agree, but not sure. That's why I created this thread. * there would be no need to copy data from tokens into AST, passing an object would be enough (again, copy 8 instead of 32 bytes); the same applies to passing into methods - no need to pass by ref to minimise overhead I'm using string to store source content in tokens. Because of the way string in D works, there is no need for data copies. The same do I. But size of string field is still 16 bytes (half of my token size). These considerations are mostly about performance. I think there is also some impact on design, but couldn't find anything significant (given that currently I see a token as merely a datastructure without associated behavior). IMO token are value types. The value type might be implemented as struct or class.
Re: struct vs class for a simple token in my d lexer
On 14.05.2012 19:10, Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks On 14.05.2012 19:10, Roman D. Boiko wrote: Oops, sorry I meant to post to NG only :) Repost: Clearly you are puting too much pressure on Token. In my mind it should be real simple: struct Token{ uint col, line; uint flags;//indicated info about token, serves as both type tag and flag set; //indicates proper type once token was cooked (like 31.415926 - 3.145926e1) i.e. values are calculated union { string chars; float f_val; double d_val; uint uint_val; long long_val; ulnog ulong_val; //... anything else you may need (8 bytes are plenty) }//even then you may use up to 12bytes //total size == 24 or 20 }; Where: Each raw token at start has chars == slice of characters in text (or if not UTF-8 source = copy of source). Except for keywords and operators. Cooking is a process of calculating constant values and such (say populating symbols table will putting symbol id into token instead of leaving string slice). Do it on the fly or after the whole source - let the user choose. Value types have nice property of being real fast, I suggest you to do at least some syntetic tests before going with ref-based stuff. Pushing 4 word is cheap, indirection never is. Classes also have hidden mutex _monitor_ field so using 'class' can be best described as suicide. Yet you may go with freelist of tokens (leaving them as structs). It's an old and proven way. About row/col - if this stuff is encoded into Finite Automation (and you sure want to do something like DFA) it comes out almost at no cost. The only disadvantage is complicating DFA tables with some irregularities of true Unicode line ending sequences. It's more of nuisance then real problem though. P.S. if you real bend on performance, I suggest to run sparate Aho-Corassic-style thing for keywords, it would greatly simplify (=speed up) DFA structure if keywords are not hardcoded into automation. -- Dmitry Olshansky
Re: struct vs class for a simple token in my d lexer
struct Token{ uint col, line; uint flags;//indicated info about token, serves as both type tag and flag set; //indicates proper type once token was cooked (like 31.415926 - 3.145926e1) i.e. values are calculated union { string chars; float f_val; double d_val; uint uint_val; long long_val; ulnog ulong_val; //... anything else you may need (8 bytes are plenty) }//even then you may use up to 12bytes //total size == 24 or 20 }; I wouldn't convert the string representation to a value unless needed. Even the parser does not need to know.
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 16:41:39 UTC, Jonathan M Davis wrote: On Monday, May 14, 2012 17:10:23 Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks For the question in general, there are primarily 2 questions to consider: 1. Do you need inheritance/polymorphism? don't have inheritance. 2. Do you need a value type or a reference type? If you need inheritance/polymorphism, you have to use classes, because structs If you want a value type, you have to use structs, because classes are reference types. If you want a reference type, then you can use either a class or a struct, but it's easier with classes, because classes are always reference types, whereas structs are naturally value types, so it can take more work to make them reference types depending on what its member variables are. One other thing to consider is deterministic destruction. The only way to get deterministic destruction is to have a struct on the stack. Value types will naturally get that, but if you want a reference type with determinstic destruction, then you're probably going to have to use a ref-counted struct. In the vast majority of cases, that should be enough to decide whether you need a class or a struct. The main case that it doesn't is the case where you want a reference type and don't necessarily want a class, and that decision can get complicated. In the case of a token in a lexer, I would definitely expect that to be a value type, which means using a struct. - Jonathan M Davis Semantics is clearly of value type. But it would be nice to minimize size of instance to be copied. (I could simply split it into two, if some part is not used in most scenarios.) Just curious: how to implement a struct as ref type? I could add indirection (but then why not just use a class?), or simply pass by ref into all methods. Are there any other options? Thanks to everybody for your feedback, it looks like I'll stay with struct.
Re: struct vs class for a simple token in my d lexer
On 14.05.2012 21:16, Tobias Pankrath wrote: struct Token{ uint col, line; uint flags;//indicated info about token, serves as both type tag and flag set; //indicates proper type once token was cooked (like 31.415926 - 3.145926e1) i.e. values are calculated union { string chars; float f_val; double d_val; uint uint_val; long long_val; ulnog ulong_val; //... anything else you may need (8 bytes are plenty) }//even then you may use up to 12bytes //total size == 24 or 20 }; I wouldn't convert the string representation to a value unless needed. Even the parser does not need to know. Thx for snipping out the gist of it :) See last sentence, flexibility is the king: Where: Each raw token at start has chars == slice of characters in text (or if not UTF-8 source = copy of source). Except for keywords and operators. Cooking is a process of calculating constant values and such (say populating symbols table will putting symbol id into token instead of leaving string slice). Do it on the fly or after the whole source - let the user choose. -- Dmitry Olshansky
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 17:05:17 UTC, Dmitry Olshansky wrote: On 14.05.2012 19:10, Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks On 14.05.2012 19:10, Roman D. Boiko wrote: Oops, sorry I meant to post to NG only :) Repost: Clearly you are puting too much pressure on Token. In my mind it should be real simple: struct Token{ uint col, line; uint flags;//indicated info about token, serves as both type tag and flag set; //indicates proper type once token was cooked (like 31.415926 - 3.145926e1) i.e. values are calculated union { string chars; float f_val; double d_val; uint uint_val; long long_val; ulnog ulong_val; //... anything else you may need (8 bytes are plenty) }//even then you may use up to 12bytes //total size == 24 or 20 }; Where: Each raw token at start has chars == slice of characters in text (or if not UTF-8 source = copy of source). Except for keywords and operators. Cooking is a process of calculating constant values and such (say populating symbols table will putting symbol id into token instead of leaving string slice). Do it on the fly or after the whole source - let the user choose. Value types have nice property of being real fast, I suggest you to do at least some syntetic tests before going with ref-based stuff. Pushing 4 word is cheap, indirection never is. Classes also have hidden mutex _monitor_ field so using 'class' can be best described as suicide. Yet you may go with freelist of tokens (leaving them as structs). It's an old and proven way. About row/col - if this stuff is encoded into Finite Automation (and you sure want to do something like DFA) it comes out almost at no cost. The only disadvantage is complicating DFA tables with some irregularities of true Unicode line ending sequences. It's more of nuisance then real problem though. P.S. if you real bend on performance, I suggest to run sparate Aho-Corassic-style thing for keywords, it would greatly simplify (=speed up) DFA structure if keywords are not hardcoded into automation. Thanks Dmitry, I think I'll need to contact you privately about some details later.
Re: struct vs class for a simple token in my d lexer
On 14.05.2012 21:20, Roman D. Boiko wrote: On Monday, 14 May 2012 at 16:41:39 UTC, Jonathan M Davis wrote: On Monday, May 14, 2012 17:10:23 Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks For the question in general, there are primarily 2 questions to consider: 1. Do you need inheritance/polymorphism? don't have inheritance. 2. Do you need a value type or a reference type? If you need inheritance/polymorphism, you have to use classes, because structs If you want a value type, you have to use structs, because classes are reference types. If you want a reference type, then you can use either a class or a struct, but it's easier with classes, because classes are always reference types, whereas structs are naturally value types, so it can take more work to make them reference types depending on what its member variables are. One other thing to consider is deterministic destruction. The only way to get deterministic destruction is to have a struct on the stack. Value types will naturally get that, but if you want a reference type with determinstic destruction, then you're probably going to have to use a ref-counted struct. In the vast majority of cases, that should be enough to decide whether you need a class or a struct. The main case that it doesn't is the case where you want a reference type and don't necessarily want a class, and that decision can get complicated. In the case of a token in a lexer, I would definitely expect that to be a value type, which means using a struct. - Jonathan M Davis Semantics is clearly of value type. But it would be nice to minimize size of instance to be copied. (I could simply split it into two, if some part is not used in most scenarios.) Just curious: how to implement a struct as ref type? I could add indirection (but then why not just use a class?), or simply pass by ref into all methods. Are there any other options? Use the damn pointer ;) In a few words (lines) overwrite struct contents (first 4-8 bytes) with pointer to next free token: //setup: void get_some_memory() { Token pool = new Token[block_size]; for(size_t i=0;ipool.length-1; i++) *(void**)(tok.ptr+i) = tok.ptr+i+1; *(void**)tok[$-1] = null; //end of list } Token* head = pool.ptr;//this guy in TLS //usage: Token* new_tok(){ return head ? get_some_memory(), head : head; } void free_tok(Token* tok){ *(void**)tok = head; head = tok; } Untested but trustworthy ;) Thanks to everybody for your feedback, it looks like I'll stay with struct. -- Dmitry Olshansky
Re: struct vs class for a simple token in my d lexer
On 14.05.2012 21:33, Dmitry Olshansky wrote: On 14.05.2012 21:20, Roman D. Boiko wrote: On Monday, 14 May 2012 at 16:41:39 UTC, Jonathan M Davis wrote: On Monday, May 14, 2012 17:10:23 Roman D. Boiko wrote: (Subj.) I'm in doubt which to choose for my case, but this is a generic question. http://forum.dlang.org/post/odcrgqxoldrktdtar...@forum.dlang.org Cross-posting here. I would appreciate any feedback. (Whether to reply in this or that thread is up to you.) Thanks For the question in general, there are primarily 2 questions to consider: 1. Do you need inheritance/polymorphism? don't have inheritance. 2. Do you need a value type or a reference type? If you need inheritance/polymorphism, you have to use classes, because structs If you want a value type, you have to use structs, because classes are reference types. If you want a reference type, then you can use either a class or a struct, but it's easier with classes, because classes are always reference types, whereas structs are naturally value types, so it can take more work to make them reference types depending on what its member variables are. One other thing to consider is deterministic destruction. The only way to get deterministic destruction is to have a struct on the stack. Value types will naturally get that, but if you want a reference type with determinstic destruction, then you're probably going to have to use a ref-counted struct. In the vast majority of cases, that should be enough to decide whether you need a class or a struct. The main case that it doesn't is the case where you want a reference type and don't necessarily want a class, and that decision can get complicated. In the case of a token in a lexer, I would definitely expect that to be a value type, which means using a struct. - Jonathan M Davis Semantics is clearly of value type. But it would be nice to minimize size of instance to be copied. (I could simply split it into two, if some part is not used in most scenarios.) Just curious: how to implement a struct as ref type? I could add indirection (but then why not just use a class?), or simply pass by ref into all methods. Are there any other options? Use the damn pointer ;) In a few words (lines) overwrite struct contents (first 4-8 bytes) with pointer to next free token: //setup: void get_some_memory() { Token pool = new Token[block_size]; for(size_t i=0;ipool.length-1; i++) *(void**)(tok.ptr+i) = tok.ptr+i+1; *(void**)tok[$-1] = null; //end of list } Token* head = pool.ptr;//this guy in TLS //usage: Token* new_tok(){ if(!head) get_some_memory(); Token* r = head; head = *(token**)head; return r; } Not so trustworthy :o) But hopefully you get the idea. See something simillar in std.regex, though pointer in there also serves for intrusive linked-list. void free_tok(Token* tok){ *(void**)tok = head; head = tok; } Untested but trustworthy ;) Thanks to everybody for your feedback, it looks like I'll stay with struct. -- Dmitry Olshansky
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 17:37:02 UTC, Dmitry Olshansky wrote: But hopefully you get the idea. See something simillar in std.regex, though pointer in there also serves for intrusive linked-list. Thanks, most likely I'll go your way.
Re: struct vs class for a simple token in my d lexer
On Monday, 14 May 2012 at 18:00:42 UTC, Roman D. Boiko wrote: On Monday, 14 May 2012 at 17:37:02 UTC, Dmitry Olshansky wrote: But hopefully you get the idea. See something simillar in std.regex, though pointer in there also serves for intrusive linked-list. Thanks, most likely I'll go your way. If you don't mind doing some lite informational reading, read up on 'lex and yacc'. ISBN: 1-56592-000-7; Hope I got that right. I'm not telling you to use C (or the other tools mind you), but it does go into handling tokens of multiple types as well as managing them using pointers and unions. A good portion of that can carry over for your lexer and project.
struct vs class
Hello, There seems to be 2 main differences between structs classes: 1. structs instances are direct values, implement value semantics; while class instances are referenced (actually pointed) 2. classes can be subtyped/subclassed in a simple way; structs cannot be really subtyped -- but there is the alias this hack I am trying to understand what should be the rationale behind choosing one or the other form of structured type. Letting aside subtyping considerations, meaning concentrating on the consequences of the first point above. Here are my views on the topic: * On the semantic side: An element should be referenced when its meaning is of a thing, an entity that has an identity distinct from its value; a things remains itself whatever its evolution in time; it can also be multiply referenced. For instance, a visual form that can change would be a thing. An element should be a value type when it provides information about a thing; a value makes no sense by itself, it is bound to what it describes an aspect of; referencing a value is meaningless, only copy makes no sense. For instance, the position color of a visual form should be values. * On the efficiency side: Struct instances have fast creation, because allocated on the stack (*)? Class instances are costly to create. But then, passing class instances around is light, since only a reference is copied, while struct instances are copied at the field level. Both of these points may conflict with semantic considerations above: we may want to use structs for fast creation, but if ever they mean things, we must think at referencing them manually and/or using ref parameters. We may want to use classes for light passing, but if they mean values, we must either never assign them or manually copy their content. It's playing with fire: very dangerous risks of semantic breaks in both cases... Here is an example: a module implementating general-purpose tree/node structure. Let us say there are both a Tree Node types -- the nodes do not implement global methods, only the tree does. So, a node just holds an element and a set of child nodes, possibly methods to manipulate these fields. A tree in addition has methods to traverse nodes, search, insert/remove, whatever... What kinds should be Node Tree? Why? Are there sensible alternatives? If yes, what are the advantages and drawback of each? In what cases? (questions, questions, questions...) Denis (*) Is this true? And why is the stack more efficient than the heap? -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: struct vs class
On Sunday 14 November 2010 03:08:49 spir wrote: Hello, There seems to be 2 main differences between structs classes: 1. structs instances are direct values, implement value semantics; while class instances are referenced (actually pointed) 2. classes can be subtyped/subclassed in a simple way; structs cannot be really subtyped -- but there is the alias this hack The main thing to remember between structs and classes is that classes are polymorphic. If you want polymorphism, use a class. If you don't use a struct. Now, if you want a type which is _always_ a reference, then you should probably choose a class, but it's quite easy to have a struct which is a reference type by having its member variables are on the heap and don't get deep copied be a postblit constructor. It is more immediately clear, though, that a class is a reference type. You can get more nuanced on the reasons why you should pick a struct or a class, but polymorphism is really what it generally comes down to. If you never intend to subclass it or have it implement interfaces, then it should probably be a struct. - Jonathan M Davis
Re: struct vs class
spir: a value makes no sense by itself, it is bound to what it describes an aspect of; referencing a value is meaningless, only copy makes no sense. For instance, the position color of a visual form should be values. Structs may have a meaning by themselves, all kind of member functions, and you may manage structs by pointer. Struct instances have fast creation, because allocated on the stack (*)? You may allocate them on the heap too, with new. And if you put a struct inside an object instance, among its fields, then the struct is allocated where the class instance is allocated, generally (but not always) on the heap. Structs may also be allocated in the static section, like static variable, and as global constant too. Class instances are costly to create. But then, passing class instances around is light, since only a reference is copied, while struct instances are copied at the field level. But structs may also be passed around by ref, and by pointer. What kinds should be Node Tree? Why? Are there sensible alternatives? If yes, what are the advantages and drawback of each? In what cases? If efficiency is not so strong, then using classes is the simpler solution. Otherwise you want to use structs plus various kinds of C hacks. (*) Is this true? And why is the stack more efficient than the heap? In Java the GC keeps the objects in separated groups, the first generation is managed as a stack, so allocation is almost as fast as stack allocation. But current D GC is more primitive, it uses a more complex allocation scheme that requires more time. Allocation on a stack is easy, you ideally only need to increment an index/pointer... Bye, bearophile
Re: struct vs class
On 14/11/2010 11:08, spir wrote: Hello, There seems to be 2 main differences between structs classes: 1. structs instances are direct values, implement value semantics; while class instances are referenced (actually pointed) 2. classes can be subtyped/subclassed in a simple way; structs cannot be really subtyped -- but there is the alias this hack I am trying to understand what should be the rationale behind choosing or the other form of structured type. Letting aside subtyping considerations, meaning concentrating on the consequences of the first point above. Here are my views on the topic: * On the semantic side: An element should be referenced when its meaning is of a thing, an entity that has an identity distinct from its value; a things remains itself whatever its evolution in time; it can also be multiply referenced. For instance, a visual form that can change would be a thing. An element should be a value type when it provides information about a thing; a value makes no sense by itself, it is bound to what it describes an aspect of; referencing a value is meaningless, only copy makes no sense. For instance, the position color of a visual form should be values. One of the best descriptions of the differences I've seen so far. * On the efficiency side: Struct instances have fast creation, because allocated on the stack (*)? Class instances are costly to create. But then, passing class instances around is light, since only a reference is copied, while struct instances are copied at the field level. Structs get allocated on the stack when used as local vars, they also get embedded in classes when they are members. i.e. if you add a 40 byte struct to a class, the class instance size goes up by ~40 bytes (depending on padding). You can still new a Struct if needed and you can always use ref plain pointers as well, so you can easily blur the line of Structs not having identity. Struct's don't have a virtual table pointer or a monitor pointer, so they can be smaller than class instances. You can also precisely control the content and layout of a struct, which you can't do with a class; so you'd have to use Structs when doing vertices in 3d programs that you want to pass to OpenGL/DirectX Both of these points may conflict with semantic considerations above: we may want to use structs for fast creation, but if ever they mean things, we must think at referencing them manually and/or using ref parameters. We may want to use classes for light passing, but if they mean values, we must either never assign them or manually copy their content. It's playing with fire: very dangerous risks of semantic breaks in both cases... Perhaps, but they are tools to implement a program design; it's the program design that should be driving your choices not abstract semantic considerations. Go down that route and you'll never get anything done. Here is an example: a module implementating general-purpose tree/node structure. Let us say there are both a Tree Node types -- the nodes do not implement global methods, only the tree does. So, a node just holds an element and a set of child nodes, possibly methods to manipulate these fields. A tree in addition has methods to traverse nodes, search, insert/remove, whatever... What kinds should be Node Tree? Why? Are there sensible alternatives? If yes, what are the advantages and drawback of each? In what cases? (questions, questions, questions...) Well Tree would probably be a class as you are likely to be passing it around a lot and Node types would be structs. For Node's you don't need inheritance, you want to keep their size as small as possible and they are not visible outside the context of the tree. And on the other hand, you probably don't want virtual methods in your tree either, so you could make that a smart pointer type struct as well and then you've got a struct masquerading as a reference type... Denis (*) Is this true? And why is the stack more efficient than the heap? You can allocate from the stack in amortised constant time; usually a very fast time. If you need 10 bytes of stack, you just subtract 10 from the stack pointer which is a single ASM instruction and as long as you don't hit the bottom of the stack you are done. If you do hit the bottom of the stack (on windows/linux) you'll attempt to access none accessible memory; this will invoke the OS's memory manager. If you've got enough free memory and free address space you'll be given a new stack page and things will continue, otherwise you'll get a stack overflow exception/seg fault. Allocating new memory runs through D runtime and in principal may take an unbounded amount of time to find/allocate the size request. If you program has a very fragmented heap and you've loads of memory allocated it might take the allocator a very long time to determine it doesn't have any free memory and then finally go
Re: struct vs class
On Sun, 14 Nov 2010 03:32:18 -0800 Jonathan M Davis jmdavisp...@gmx.com wrote: On Sunday 14 November 2010 03:08:49 spir wrote: Hello, There seems to be 2 main differences between structs classes: 1. structs instances are direct values, implement value semantics; while class instances are referenced (actually pointed) 2. classes can be subtyped/subclassed in a simple way; structs cannot be really subtyped -- but there is the alias this hack The main thing to remember between structs and classes is that classes are polymorphic. If you want polymorphism, use a class. If you don't use a struct. Now, if you want a type which is _always_ a reference, then you should probably choose a class, but it's quite easy to have a struct which is a reference type by having its member variables are on the heap and don't get deep copied be a postblit constructor. It is more immediately clear, though, that a class is a reference type. You can get more nuanced on the reasons why you should pick a struct or a class, but polymorphism is really what it generally comes down to. If you never intend to subclass it or have it implement interfaces, then it should probably be a struct. Thank you, Jonathan. But what about the copy issue. For instance, in a parsing lib, I currently have a Source class that is a kind of cursored text (think at a text file), so it's only: class Source { string text; uint index; this (string text, uint index) { this.text = text; this.index = index; } } The advantages that match functions return a source that has stepped forward after successful match (hope you see what I mean, it's a common issue in parsing). Conceptually, it's pure data, meaning it should be a struct. Also, as you point above, it requires no polymorphism. But I made it a class, because: * It's created only once, so heavier creation on the heap is irrelevant. * It's passed from match method to match method huge numbers of time (can be millions of times when parsing code). If I had a struct, it would be copied! (Even if the text itself can be prevented from copy by putting it in a plain array, or pointed, the fields are still copied.) * Higher-level patterns that delegate matching to sub-patterns directly get updated source (with new index), precisely because the source is referenced. For instance, the actual match method of the Choice pattern type holds: // ... foreach (Pattern pattern ; this.patterns) { try return pattern.check(source); // *** catch (MatchError e) { // ... } } // ... } The marked line works because Source is referenced. Else, I would have to update source.index manually. Similarly, for a Composition pattern type (every sub-pattern must match in sequence): foreach (Pattern pattern ; patterns) { result = pattern.check(source); nodes ~= result.node; } The source is automagically updated by each sub-pattern match. Thus, this a case where semantic (of value) and feature (no polymorphism) rationales seem both to conflict with practical programming reasons. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: struct vs class
On Sun, 14 Nov 2010 12:02:35 + div0 d...@sourceforge.net wrote: Both of these points may conflict with semantic considerations above: we may want to use structs for fast creation, but if ever they mean things, we must think at referencing them manually and/or using ref parameters. We may want to use classes for light passing, but if they mean values, we must either never assign them or manually copy their content. It's playing with fire: very dangerous risks of semantic breaks in both cases... Perhaps, but they are tools to implement a program design; it's the program design that should be driving your choices not abstract semantic considerations. Go down that route and you'll never get anything done. I do not really get what you mean with program design as opposed to semantic considerations. I tend to think that program design should precisely be driven by semantic considerations -- and that it's the main purpose of good language design to allow this as straightforwardly as possible. A bad langage is for me one in which one can hardly express what is meant -- leading to what I call semantic distorsion ;-). So, what is program design for you? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: struct vs class
On Sunday 14 November 2010 04:14:29 spir wrote: On Sun, 14 Nov 2010 03:32:18 -0800 Jonathan M Davis jmdavisp...@gmx.com wrote: On Sunday 14 November 2010 03:08:49 spir wrote: Hello, There seems to be 2 main differences between structs classes: 1. structs instances are direct values, implement value semantics; while class instances are referenced (actually pointed) 2. classes can be subtyped/subclassed in a simple way; structs cannot be really subtyped -- but there is the alias this hack The main thing to remember between structs and classes is that classes are polymorphic. If you want polymorphism, use a class. If you don't use a struct. Now, if you want a type which is _always_ a reference, then you should probably choose a class, but it's quite easy to have a struct which is a reference type by having its member variables are on the heap and don't get deep copied be a postblit constructor. It is more immediately clear, though, that a class is a reference type. You can get more nuanced on the reasons why you should pick a struct or a class, but polymorphism is really what it generally comes down to. If you never intend to subclass it or have it implement interfaces, then it should probably be a struct. Thank you, Jonathan. But what about the copy issue. For instance, in a parsing lib, I currently have a Source class that is a kind of cursored text (think at a text file), so it's only: class Source { string text; uint index; this (string text, uint index) { this.text = text; this.index = index; } } The advantages that match functions return a source that has stepped forward after successful match (hope you see what I mean, it's a common issue in parsing). Conceptually, it's pure data, meaning it should be a struct. Also, as you point above, it requires no polymorphism. But I made it a class, because: * It's created only once, so heavier creation on the heap is irrelevant. * It's passed from match method to match method huge numbers of time (can be millions of times when parsing code). If I had a struct, it would be copied! (Even if the text itself can be prevented from copy by putting it in a plain array, or pointed, the fields are still copied.) * Higher-level patterns that delegate matching to sub-patterns directly get updated source (with new index), precisely because the source is referenced. For instance, the actual match method of the Choice pattern type holds: // ... foreach (Pattern pattern ; this.patterns) { try return pattern.check(source); // *** catch (MatchError e) { // ... } } // ... } The marked line works because Source is referenced. Else, I would have to update source.index manually. Similarly, for a Composition pattern type (every sub-pattern must match in sequence): foreach (Pattern pattern ; patterns) { result = pattern.check(source); nodes ~= result.node; } The source is automagically updated by each sub-pattern match. Thus, this a case where semantic (of value) and feature (no polymorphism) rationales seem both to conflict with practical programming reasons. Well, like I said, it can be more nuanced. Polymorphism is the main thing, but other factors can matter. In this case, you have an efficiency problem in using a struct. The are several ways around that: 1. Make the struct a reference type, making its internals pointers or references. 2. Make the struct a value type, but make its internals pointers are references and use COW (copy-on-write). 3. Use a pointer to a struct. 4. Use a class. Personally, I think that #1 can be useful, but generally that's probably not what you want. #2 doesn't work correctly right now due to bugs regarding destructors, and it's a pretty complicated solution anyway. As for #3 and #4, if you're not going to use polymorphism, then there really isn't much difference between using pointers to structs and making the type a class - the main difference between a pointer and a reference being that a reference is polymorphic (if you had a pointer to a class, it wouldn't be polymorphic), so it's arguably better to use pointer to a struct than a class when it doesn't need to be polymorphic, but I suppose that it's a matter of taste. If you make it a struct, you at least _can_ stick it on the stack if you want though. It also makes them easier to copy, since you don't have to declare a clone() function or something similar. However, making it a class makes it obvious that it's intended to be used as a reference type rather than a value type, so it all depends on what you're trying to do. - Jonathan M Davis
Re: struct vs class
spir wrote: On Sun, 14 Nov 2010 12:02:35 + div0 d...@sourceforge.net wrote: Both of these points may conflict with semantic considerations above: we may want to use structs for fast creation, but if ever they mean things, we must think at referencing them manually and/or using ref parameters. We may want to use classes for light passing, but if they mean values, we must either never assign them or manually copy their content. It's playing with fire: very dangerous risks of semantic breaks in both cases... Perhaps, but they are tools to implement a program design; it's the program design that should be driving your choices not abstract semantic considerations. Go down that route and you'll never get anything done. I do not really get what you mean with program design as opposed to semantic considerations. I tend to think that program design should precisely be driven by semantic considerations -- and that it's the main purpose of good language design to allow this as straightforwardly as possible. A bad langage is for me one in which one can hardly express what is meant -- leading to what I call semantic distorsion ;-). So, what is program design for you? Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com If I may add my 2 cents: program design is where, in another response, you choose to pass a cursor into a source text by reference and have methods update that reference directly instead of returning a new cursor. You have chosen a class, but a pointer inside a struct it could be done as well.