Re: best approach to code hierarchical classes ?

2021-06-09 Thread someone via Digitalmars-d-learn

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?

2021-06-09 Thread Gregor Mückl via Digitalmars-d-learn

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?

2021-06-09 Thread Adam D Ruppe via Digitalmars-d-learn

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?

2021-06-09 Thread evilrat via Digitalmars-d-learn

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?

2021-06-09 Thread Gregor Mückl via Digitalmars-d-learn

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?

2021-06-09 Thread mw via Digitalmars-d-learn

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

2021-06-09 Thread JG via Digitalmars-d-learn
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

2021-06-09 Thread kinke via Digitalmars-d-learn

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?

2021-06-09 Thread Marcone via Digitalmars-d-learn

std.file.append(file, "\nApple");
std.file.append(file, "\nBanana");

Result:

AppleBanana



Why std.file.append() new lind "\n" not work in Windows?

2021-06-09 Thread Marcone via Digitalmars-d-learn

std.file.append("file; \nApple");
std.file.append("file; \nBanana");

Result:

AppleBanana


Re: Why std.file.append() new lind "\n" not work in Windows?

2021-06-09 Thread Marcone via Digitalmars-d-learn

std.file.append(file; "\nApple");
std.file.append(file; "\nBanana");

Result:

AppleBanana




Re: Why std.file.append() new lind "\n" not work in Windows?

2021-06-09 Thread tsbockman via Digitalmars-d-learn

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?

2021-06-09 Thread Marcone via Digitalmars-d-learn

I want add Yes.keepTerminator flag on lineSplitter.


Re: Shift operator, unexpected result

2021-06-09 Thread tsbockman via Digitalmars-d-learn

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?

2021-06-09 Thread Ali Çehreli via Digitalmars-d-learn

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?

2021-06-09 Thread nov via Digitalmars-d-learn

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

2021-06-09 Thread jfondren via Digitalmars-d-learn

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.