Re: best approach to code hierarchical classes ?
On Tuesday, 8 June 2021 at 02:37:44 UTC, someone wrote: On Tuesday, 8 June 2021 at 02:05:27 UTC, Paul Backus wrote: Your module and class are both named `classComputers`, with an `s` at the end. You should change one of the to have a different name so that there's no ambiguity. Although I am still not being able to solve the import issue for the child code on my nested-classes (low priority by the time being), I have now a more pressing issue. But first and foremost: almost sure you'll find my code style noisy given the heavily-used attribue/function properties, but this is solely to remind me how things work in a new language, what will be obvious to an experienced D developer (default attributes) it is not obvious to me right now ... spare me the style, will you ? I moved all the boilerplate code to manage the collection to classCollectionItems which also has a nested child classCollectionItem (since I'll be widely using them as the basis for hierarchical class models) and from then on I inherit the class on my final classComputers/classComputer code which is my first test-bed app in D. Before moving the code to the new generic abstract classes the code below worked flawlessly, and still works albeit for a minor detail: I now **have an issue accessing the collection** (previously defined in the base classCollectionItems) through my derived classComputers class: please, look for the comment block marked with +++ below. The base classCollectionItems will always have a collection named items, and each derived class I will make from it should have a reference to it renamed accordingly; eg: computers in the case of my classComputers class. Later I will plan to make an interface to hide all the inner details and hide the items property of the base class once and for all, leaving each new derived class' own renamed property publicly accessible). So when the issue first appeared on my new refactored code I **started playing with alias to no avail** -and even making a new computers property initialized with items (but then I figured it out that this will be copying the array -not referencing it, so this will be a no-go). Some advice please ? ```d #!/bin/dmd module dmclassescomputers; import std.string; abstract private class classCollectionItems { classCollectionItems lhs; classCollectionItems rhs; int opApply(int delegate(classCollectionItem) dg) { /// boilerplate code to handle the class's default collection int lintResult = 0; /// must find a better name foreach (lobjItem; items) { /// looping over the computers starting in current node lintResult = dg(lobjItem); /// passing single object to the loop body if (lintResult != 0) { break; } } if (lintResult != 0 && lhs ! is null) { lintResult = lhs.opApply(dg); } /// recursing child nodes if (lintResult != 0 && rhs ! is null) { lintResult = rhs.opApply(dg); } /// recursing child nodes return lintResult; } public @property classCollectionItem[] items; alias items this; /// ie: default property final public @property const long count0() { return this.items.empty ? 0L : this.items.length - 1L; } final public @property const long count1() { return this.items.empty ? 0L : this.items.length; } final public @property const long count() { return this.count1; } final public @property const bool empty() { return this.items.empty; } abstract public bool add(in string lstrID) { return false; } abstract public bool remove(in string lstrID) { return false; } abstract public bool removeAll() { return false; } abstract class classCollectionItem { private ulong pintPosition0 = 0L; /// keep in mind that array positions are zero-based final public @property const ulong position0() { return this.pintPosition0; } final public @property const ulong position1() { return this.pintPosition0 + 1L; } final public @property const ulong countAbove() { return this.outer.items.empty ? 0L : this.pintPosition0; } final public @property const ulong countBelow() { return this.outer.items.empty ? 0L : this.outer.length - this.pintPosition0 - 1L; } /// eg: for position0=0 → countAbove=0=(position0=0) & countBelow=2=(length=3)-(position0=0)-1 /// eg: for position0=1 → countAbove=1=(position0=1) & countBelow=1=(length=3)-(position0=1)-1 /// eg: for position0=2 → countAbove=2=(position0=2) & countBelow=0=(length=3)-(position0=2)-1 final public @property classCollectionItem first() { return this.outer.items.empty ? null : this.outer.items[0L]; } final public @property classCollectionItem previous() { return this.outer.items.empty || this.countAbove == 0L ? null : this.outer.items[this.pintPosition0 - 1L]; } final public @property classCollectionItem next() { return this.outer.items.empty || this.countBelow == 0L ? null : this.oute
Class member initialization with new points to a single instance?
Consider the following code: ```d class Foo { } class Bar { Foo foo = new Foo(); } void main() { Bar b1 = new Bar(); Bar b2 = new Bar(); assert(b1.foo != b2.foo); } ``` The assert fails. This is completely surprising to me. Is this actually expected?
Re: Class member initialization with new points to a single instance?
On Wednesday, 9 June 2021 at 17:56:24 UTC, Gregor Mückl wrote: class Bar { Foo foo = new Foo(); } This is a static initialization The assert fails. This is completely surprising to me. Is this actually expected? Yes, it is expected if you are familiar with the spec. All member = x things inside a class or struct declaration are static initializers. These are CTFE'd into the same form as a literal. So there's one instance of Foo there which is assigned to the object member before the constructor runs. For a runtime initialization, you use a constructor.
Re: Class member initialization with new points to a single instance?
On Wednesday, 9 June 2021 at 17:56:24 UTC, Gregor Mückl wrote: Consider the following code: ```d class Foo { } class Bar { Foo foo = new Foo(); } void main() { Bar b1 = new Bar(); Bar b2 = new Bar(); assert(b1.foo != b2.foo); } ``` The assert fails. This is completely surprising to me. Is this actually expected? By design. What you see is CTFE instance shared through class member initializer. Use Bar ctor instead if you want them to be unique. Yep, confusing for the first time.
Re: Class member initialization with new points to a single instance?
On Wednesday, 9 June 2021 at 18:04:54 UTC, evilrat wrote: On Wednesday, 9 June 2021 at 17:56:24 UTC, Gregor Mückl wrote: Consider the following code: ```d class Foo { } class Bar { Foo foo = new Foo(); } void main() { Bar b1 = new Bar(); Bar b2 = new Bar(); assert(b1.foo != b2.foo); } ``` The assert fails. This is completely surprising to me. Is this actually expected? By design. What you see is CTFE instance shared through class member initializer. Use Bar ctor instead if you want them to be unique. Yep, confusing for the first time. My two cents: I think this should be changed because all other common languages that support equivalent syntax have settled on runtime initialization for this. But it's probably too deeply embedded into the language now. :(
Re: Class member initialization with new points to a single instance?
On Wednesday, 9 June 2021 at 18:12:01 UTC, Gregor Mückl wrote: On Wednesday, 9 June 2021 at 18:04:54 UTC, evilrat wrote: On Wednesday, 9 June 2021 at 17:56:24 UTC, Gregor Mückl wrote: Consider the following code: ```d class Foo { } class Bar { Foo foo = new Foo(); } void main() { Bar b1 = new Bar(); Bar b2 = new Bar(); assert(b1.foo != b2.foo); } ``` The assert fails. This is completely surprising to me. Is this actually expected? By design. What you see is CTFE instance shared through class member initializer. Use Bar ctor instead if you want them to be unique. Yep, confusing for the first time. My two cents: I think this should be changed because all other common languages that support equivalent syntax have settled on runtime initialization for this. But it's probably too deeply embedded into the language now. :( Can we add (enforcement) `static` in this case, to make it clear. It's so confusing.
Shift operator, unexpected result
I found the following behaviour, as part of a more complicated algorithm, unexpected. The program: import std; void main() { int n = 64; writeln(123uL>>n); } produces: 123 I would expect 0. What is the rationale for this behaviour or is it a bug?
Re: Shift operator, unexpected result
On Wednesday, 9 June 2021 at 19:13:10 UTC, JG wrote: I found the following behaviour, as part of a more complicated algorithm, unexpected. The program: import std; void main() { int n = 64; writeln(123uL>>n); } produces: 123 I would expect 0. What is the rationale for this behaviour or is it a bug? This is undefined behavior as in other languages, see §3 in https://dlang.org/spec/expression.html#shift_expressions.
Re: Why std.file.append() new lind "\n" not work in Windows?
std.file.append(file, "\nApple"); std.file.append(file, "\nBanana"); Result: AppleBanana
Why std.file.append() new lind "\n" not work in Windows?
std.file.append("file; \nApple"); std.file.append("file; \nBanana"); Result: AppleBanana
Re: Why std.file.append() new lind "\n" not work in Windows?
std.file.append(file; "\nApple"); std.file.append(file; "\nBanana"); Result: AppleBanana
Re: Why std.file.append() new lind "\n" not work in Windows?
On Wednesday, 9 June 2021 at 21:10:58 UTC, Marcone wrote: std.file.append("file; \nApple"); std.file.append("file; \nBanana"); Result: AppleBanana Not all systems use the same char sequence for line breaks. In particular, Microsoft Windows uses "\r\n". You can use [`std.ascii.newline`](https://dlang.org/phobos/std_ascii.html#newline) to write platform-independent code. Functions like `std.stdio.writeln` that write a newline at the end of the message will also do the right thing.
How use lineSplitter with KeepTerminator flag?
I want add Yes.keepTerminator flag on lineSplitter.
Re: Shift operator, unexpected result
On Wednesday, 9 June 2021 at 19:13:10 UTC, JG wrote: I found the following behaviour, as part of a more complicated algorithm, unexpected. The program: import std; void main() { int n = 64; writeln(123uL>>n); } produces: 123 I would expect 0. What is the rationale for this behaviour or is it a bug? Because it is a high-performance systems programming language, the designers of D decided to make the arithmetic operations of basic types map directly to the arithmetic operations built in to the CPU; most operations are a single instruction. The benefit of this is higher performance and smaller binaries. The disadvantage is that the behaviour of the built in CPU operations sometimes differs from ordinary arithmetic in surprising and frustrating ways. If you want to trade a some speed for correctness/predictability, try my `checkedint` Dub package. Either way, take a glance at the [introduction to the documentation](https://checkedint.dpldocs.info/checkedint.html), where I list some of the quirks of CPU integer behaviour. For bit shifts, specifically, many CPUs ignore all but the bottom `log2(T.sizeof * 8)` bits of the right-hand operand. (`core.bitop.bsr` can be used to do very fast integer `log2` operations, and works in CTFE.) Thus, `a >> b` behaves like `a >> (b & c)`, where `c` is `(T.sizeof * 8) - 1`. For unsigned types, the behaviour that you very reasonably expect requires two additional instruction on x86, which looks like this: `(b <= c)? (a >> b) : 0`. (This should be branchless thanks to the `cmov` instruction.) For signed types, some additional work is required to handle negative shifts; see my `checkedint` package.
Re: How use lineSplitter with KeepTerminator flag?
On 6/9/21 2:48 PM, Marcone wrote: I want add Yes.keepTerminator flag on lineSplitter. It's a template parameter, which is specified after an exclamation mark. The trouble is, Flag is defined in std.typecons. I would expect std.typecons (or at least Flag from it) to be publicly imported but it is not. I think that is an interface bug: If it appears in the interface (of lineSplitter), it should be available without needing to import additional modules. import std.string; import std.stdio; import std.typecons; void main() { auto input = "line1\nline2\nline3"; auto range = input.lineSplitter!(Yes.keepTerminator); writeln(range); } Ali
Re: Why std.file.append() new lind "\n" not work in Windows?
On Wednesday, 9 June 2021 at 21:12:46 UTC, Marcone wrote: Result: AppleBanana open with wordpad or open with notepad++ or display with "type filename" command
Re: Asking for D solution
On Monday, 7 June 2021 at 23:40:52 UTC, Alexander Tretyak wrote: And now I'm looking for people who can translate this task into other languages (D, Rust, Swift, etc.), and then I will compare all implementations by code readability and by performance. So, can someone provide the most idiomatic D solution to this task? I can pay for that (not very much though). This isn't quite what you're asking for, so no need to pay: https://github.com/jrfondren/pqmarkup-lite/tree/master/d This adds tests.d which is written in the style of tests.py, and pqmarkup_lite.d which is written in the style (with more differences required) of pqmarkup_lite1.nim. So this is more of a demonstration of D's range than of particularly idiomatic D. Due to some mistakes that I made while rewriting the Nim, this version is still failing seven(+2) of the tests. You can run it through the tests with one of ./tests.d or dmd -i -run tests.d pqmarkup_lite.d I welcome anyone else taking the D and improving on it.