Re: short guide on getting started with D

2023-04-04 Thread thinkunix via Digitalmars-d-learn

cgenie via Digitalmars-d-learn wrote:

Hello,

I created a short guide on getting started with D: 
https://blog.mmksoft.uk/#A%20short%20guide%20on%20getting%20started%20with%20D%20programming 



This is because I recently I started to explore the language and, having 
read the forum, I see DUB being discouraged quite often.


I would appreciate any remarks.



My observations:
#1 typo:  After that, add this meso.build file:

"meso.build" should be "meson.build"

#2 Does it matter where the dlang = import... block goes in the
meson.build file?  I added it after the "test(..." in the first
block and it seemed to work, but...

#3 where is dep?  Is it a file or do I have to create it?

I could only get you demo to work by removing the line

  dependencies: deps

from meson.build.  Then it created dub.json and dub ran it OK.

No need for a reply, just my obvservations from someone who knows
a little D and less meson.

scot




Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Apr 04, 2023 at 09:35:29PM +, Paul via Digitalmars-d-learn wrote:
[...]
> Well Steven just making the change you said reduced the execution time
> from ~6-7 secs to ~3 secs.  Then, including the 'parallel' in the
> foreach statement took it down to ~1 sec.
> 
> Boy lesson learned in appending-to and zeroing dynamic arrays in a hot
> loop!

Best practices for arrays in hot loops:
- Avoid appending if possible; instead, pre-allocate outside the loop.
- Where possible, reuse existing arrays instead of discarding old ones
  and allocating new ones.
- Use slices where possible instead of making copies of subarrays (this
  esp. applies to strings).
- Where possible, prefer sequential access over random access (take
  advantage of the CPU cache hierarchy).


T

-- 
Famous last words: I *think* this will work...


Re: Virtual method call from constructor

2023-04-04 Thread Ali Çehreli via Digitalmars-d-learn

On 4/4/23 00:08, Chris Katko wrote:
> dscanner reports this as a warning:
>
> ```D
> struct foo{
> this()
>{
>/* some initial setup */
>refresh();
>}
> void refresh() { /* setup some more stuff */}
> // [warn] a virtual call inside a constructor may lead to unexpected
> results in the derived classes
>
> }
> ```

I can understand that error for a class. Is that really a struct? If so, 
then it looks like a dscanner bug to me.


> Firstly, are all calls virtual in a struct/class in D?

All functions are by-default virtual only for classes.

To note, not the "call" but the function can be virtual. When calls are 
involved, there can be static binding and dynamic binding. Static 
binding is when a call is resolved at compile time. Dynamic binding is 
resolved at run time through the vtbl pointer.


> Is this any
> different from C++?

Yes. In C++, all functions are non-virtual by-default.

> IIRC, in C++, a struct cannot have virtual calls,

No, structs and classes are functionally exactly the same in C++. The 
only difference is their default member accessibility: public for 
structs and private for classes.


> and virtual methods are explicit keywords in classes.

Yes.

> Second, could you give me some case examples where this problem occurs?
> Is the issue if I override refresh in a derived class, and the base
> class will accidentally use child.refresh()?

Yes. :) Here is what I had learned in my C++ days: The vtbl pointer is 
stamped before the constructor is entered. However, an object is not yet 
complete without its constructor exiting. The base class's constructor 
calling a virtual function of its derived part might be disastrous 
because the derived part is not fully constructed yet. (Well, it is not 
as disastrous in D because all members have default values by-default.)


import std;

class Base {
void foo() {
writeln(__FUNCTION__);
}

this(int i) {
writeln("Entered ", __FUNCTION__);
foo();  // <-- THE PROBLEM
writeln("Exiting ", __FUNCTION__);
}
}

class Derived : Base {
override void foo() {
writeln(__FUNCTION__);
}

this(int i) {
writeln("Entered ", __FUNCTION__);
super(i);
writeln("Exiting ", __FUNCTION__);
}
}

void main() {
auto d = new Derived(42);
}

Here is the (annotated) output:

Entered deneme.Derived.this
Entered deneme.Base.this
deneme.Derived.foo<-- NO!
Exiting deneme.Base.this
Exiting deneme.Derived.this

The highlighted line is a call to a derived function but even the base 
part of the object is not finished its construction yet. The weird thing 
is Base is initiating the call but it has no idea even whether it's a 
part of an inheritance hierarchy, what other types are involved, etc.


Ali



Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Paul via Digitalmars-d-learn
On Monday, 3 April 2023 at 23:50:48 UTC, Steven Schveighoffer 
wrote:


So what you need is inside `createSpansOfNoBeacons`, take as a 
reference a `ref Span[MAX_SPANS]`, and have it return a 
`Span[]` that is a slice of that which was "alocated".


See if this helps.


Well Steven just making the change you said reduced the execution 
time from ~6-7 secs to ~3 secs.  Then, including the 'parallel' 
in the foreach statement took it down to ~1 sec.


Boy lesson learned in appending-to and zeroing dynamic arrays in 
a hot loop!




How do you work with unittest libraries in dub packages?

2023-04-04 Thread Christian Köstlin via Digitalmars-d-learn

Recently Dmytro Katyukha brought up an issue in one of my dub packages
that is supposed to be used as a library. He even went the whole way and
came up with a simple reduced example: 
https://gitlab.com/gizmomogwai/colored/-/merge_requests/3#note_1341026928.


The problem here is, that my dub package uses unit_threaded in the
unittest configuration, and only imports unit_threaded in a `version 
(unittest)` block. Previously I imported unit_threaded only in the 
individual testfunctions themselves, but I thought to reduce some typing.


When my library is now used in another project (that does not depend on 
unit_threaded) `dub test` seems to still compile my library with the 
unittest version, but it would not run the unittests of my library. So 
in the end `dub test` fails for the dependent project (as it is not 
providing unit_threaded).


Is this behavior expected?
What would be best practice to work around that?

Kind regards,
Christian


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/4/23 11:34 AM, Salih Dincer wrote:

On Tuesday, 4 April 2023 at 14:20:20 UTC, Steven Schveighoffer wrote:
parallel is a shortcut to `TaskPool.parallel`, which is indeed a 
foreach-only construct, it does not return a range.


I think what you want is `TaskPool.map`:

```d
// untested, just looking at the
taskPool.map!(/* your map function here */)
   (s.iota(len)).writeln;
```



I tried, thanks but it goes into infinite loop. For example, the first 
50 of the sequence should have been printed to the screen immediately 
without waiting.


```d
long[50] arr;
RowlandSequence_v2 range;

auto next(long a)
{
   range.popFront();
   return arr[a] = range.front();
}

void main()
{
     range = RowlandSequence_v2(7, 2);
     taskPool.map!next(iota(50))/*
     s.iota(50)
  .map!next
  .parallel//*/
  .writeln;
}
```


Keep in mind that `arr` and `range` are thread-local, and so will be 
different states for different tasks.


Though I don't really know what you are doing there.

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Salih Dincer via Digitalmars-d-learn
On Tuesday, 4 April 2023 at 14:20:20 UTC, Steven Schveighoffer 
wrote:
parallel is a shortcut to `TaskPool.parallel`, which is indeed 
a foreach-only construct, it does not return a range.


I think what you want is `TaskPool.map`:

```d
// untested, just looking at the
taskPool.map!(/* your map function here */)
   (s.iota(len)).writeln;
```



I tried, thanks but it goes into infinite loop. For example, the 
first 50 of the sequence should have been printed to the screen 
immediately without waiting.


```d
long[50] arr;
RowlandSequence_v2 range;

auto next(long a)
{
  range.popFront();
  return arr[a] = range.front();
}

void main()
{
range = RowlandSequence_v2(7, 2);
taskPool.map!next(iota(50))/*
s.iota(50)
 .map!next
 .parallel//*/
 .writeln;
}
```

On Tuesday, 4 April 2023 at 13:18:01 UTC, Ali Çehreli wrote:
I don't have time to experiment more at this time but I have 
the following chapters, which includes some of those other 
algorithms as well:


  http://ddili.org/ders/d/kosut_islemler.html


I read it, thanks...

SDB@79


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/4/23 5:24 AM, Salih Dincer wrote:

Is it necessary to enclose the code in `foreach()`? I invite Ali to tell 
me! Please explain why parallel isn't running.


parallel is a shortcut to `TaskPool.parallel`, which is indeed a 
foreach-only construct, it does not return a range.


I think what you want is `TaskPool.map`:

```d
// untested, just looking at the
taskPool.map!(/* your map function here */)
   (s.iota(len)).writeln;
```

Can't use pipelining with it, because it is a member function.

https://dlang.org/phobos/std_parallelism.html#.TaskPool.map

-Steve


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Ali Çehreli via Digitalmars-d-learn

On 4/4/23 02:24, Salih Dincer wrote:

> I don't understand what `foreach()` does :)

Hm. I forgot whether 'parallel' works only with 'foreach'. But there are 
various other algorithms in std.parallelism that may be more useful with 
range algorithm chains:


  https://dlang.org/phobos/std_parallelism.html

> in Turkish

I don't have time to experiment more at this time but I have the 
following chapters, which includes some of those other algorithms as well:


  http://ddili.org/ders/d/kosut_islemler.html

  http://ddili.org/ders/d.en/parallelism.html

Ali



Re: What do you think about using Chat GPT to create functions in D?

2023-04-04 Thread Guillaume Piolat via Digitalmars-d-learn

On Monday, 3 April 2023 at 23:38:52 UTC, Marcone wrote:

What do you think about using Chat GPT to create functions in D?


Well you can use GitHub Copilot in VSCode, and it is kind of 
interesting but at the current time seems like a distracting 
waste of time. It will probably get more useful in a few years.


LLMs repeats commonly accepted lies as gospel, so do not expect a 
well adjusted human-like opinion on anything.


Re: foreach (i; taskPool.parallel(0..2_000_000)

2023-04-04 Thread Salih Dincer via Digitalmars-d-learn
On Monday, 3 April 2023 at 22:24:18 UTC, Steven Schveighoffer 
wrote:

So for example, if you have:

```d
foreach(i; iota(0, 2_000_000).parallel)
{
   runExpensiveTask(i);
}
```

The foreach is run on the main thread, gets a `0`, then hands 
off to a task thread `runExpensiveTask(0)`. Then it gets a `1`, 
and hands off to a task thread `runExpensiveTask(1)`, etc. The 
iteration is not expensive, and is not done in parallel.


On the other hand, what you *shouldn't* do is:

```d
foreach(i; iota(0, 2_000_000).map!(x => 
runExpensiveTask(x)).parallel)

{
}
```

as this will run the expensive task *before* running any tasks.


I don't understand what `foreach()` does :)
```d
import std.range, std.algorithm : map;
import std.stdio, std.parallelism;
//import sdb.sequences : RowlandSequence_v2;/*
struct RowlandSequence_v2 {
  import std.numeric : gcd;

  long b, r, a = 3;
  enum empty = false;
  auto front() => a;
  void popFront() {
long result = 1;
while(result == 1) {
  result = gcd(r++, b);
  b += result;
}
a = result;
  }
}//*/

enum BP : long {
   // s, f, r, b = 7, /* <- beginning
   s = 178, r = 1993083484, b =  5979250449,//*/
   len = 190
}

void main()
{
  with(BP) {
long[len] arr;
auto range = RowlandSequence_v2(b, r);

s.iota(len)
 .map!((a){
range.popFront();
return arr[a] = range.front();
  }
  )
 .parallel
 .writeln;
  }
} /* PRINTS:

ParallelForeach!(MapResult!(__lambda3, 
Result))(std.parallelism.TaskPool, [5, 3, 73, 157, 7, 5, 3, 13, 
3986167223, 3, 7, 73], 1)


*/
```

Is it necessary to enclose the code in `foreach()`? I invite Ali 
to tell me! Please explain why parallel isn't running.


"Ben anlamıyor, foreach ne yapıyor  Kodu `foreach()` içine almak 
şart mı? Ali'yi davet ediyorum, bana anlatması için! Paralel() 
niye çalışmıyor, lütfen açıklayın hocam. Mümkünse Türkçe!" in 
Turkish.


SDB@79


Re: Virtual method call from constructor

2023-04-04 Thread Richard (Rikki) Andrew Cattermole via Digitalmars-d-learn

> Firstly, are all calls virtual in a struct/class in D?

In D structs are always value types without a vtable or inheritance.

Classes are always reference types with a vtable, but some of the 
methods may be final and hence not in vtable.


> Second, could you give me some case examples where this problem 
occurs? Is the issue if I override refresh in a derived class, and the 
base class will accidentally use child.refresh()?


Yes. It'll call the entry in the vtable, not the one declared in the 
class if its overridden.


> Third, is there the expectation that you should _never_ call any 
internal, private, methods inside a constructor? Or do I just 
call/structure it a different way?


No. Do what you need to do. Dscanner is a linter that may be a bit 
sensitive just in case you didn't realize that the behavior is doing 
something that you probably haven't considered, which could be problematic.




Virtual method call from constructor

2023-04-04 Thread Chris Katko via Digitalmars-d-learn

dscanner reports this as a warning:

```D
struct foo{
this()
  {
  /* some initial setup */
  refresh();
  }
void refresh() { /* setup some more stuff */}
// [warn] a virtual call inside a constructor may lead to 
unexpected results in the derived classes


}
```

Firstly, are all calls virtual in a struct/class in D? Is this 
any different from C++? IIRC, in C++, a struct cannot have 
virtual calls, and virtual methods are explicit keywords in 
classes.


Second, could you give me some case examples where this problem 
occurs? Is the issue if I override refresh in a derived class, 
and the base class will accidentally use child.refresh()?


Third, is there the expectation that you should _never_ call any 
internal, private, methods inside a constructor? Or do I just 
call/structure it a different way?


For a concrete example: I have a particle struct. It makes sense 
to me, to have initial setup code (placed in the refresh() 
function) called by this(), that later I can then call again; to 
reset the struct to an initial state in-memory without 
re-allocations.


I imagine in D that there's probably something like:

```D
particles[235] = foo.init;
```

but that blows up in a scenario where I'm only _partially_ 
resetting the struct data. For example, if I had a bunch of 
pointers to system modules, those values don't need to be nulled 
and re-set every time in this(), whereas the physical data like 
position, velocity, angle, need reset in refresh(). You could 
architect around that, but I'm trying to learn the language 
mechanics.