Re: Boneheaded question regarding compilation...

2024-04-02 Thread Dennis via Digitalmars-d-learn

On Tuesday, 2 April 2024 at 18:21:58 UTC, Mike Shah wrote:
An easier fix may be perhaps to just use 'dub' and install the 
glfw dependency. In my talk, I did everything from scratch (my 
preferred way), though I suspect using dub with glfw-d 
(https://code.dlang.org/packages/glfw-d) may provide less 
resistance.


glfw-d also provides an OpenGL hello world triangle example:

https://github.com/dkorpel/glfw-d/tree/master/examples/triangle-gl

It uses bindbc-opengl instead of glad to load OpenGL functions.


Re: Boneheaded question regarding compilation...

2024-04-02 Thread Mike Shah via Digitalmars-d-learn

On Monday, 1 April 2024 at 21:23:50 UTC, WhatMeWorry wrote:


Huge fan of Mike Shah's YouTube videos regarding D and his 
latest for D conference:


https://mshah.io/conf/24/DConf%20%20Online%202024%20_%20The%20Case%20for%20Graphics%20Programming%20in%20Dlang.pdf

So I installed github desktop app and cloned his Talks repo. 
There is a build command commented out at the top of the main.d 
file which I've been trying to compile, via the command line:


C:\Users\kheas\Documents\Talks\2024\dconf_online\hello_triangle>dmd -g -J. main.d 
./glad/gl/*.d -L-L/usr/local/lib -L-lglfw3 -of=prog && ./prog
Error: cannot find input file `.\glad\gl\*.d`
import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos
import path[1] = 
C:\D\dmd2\windows\bin64\..\..\src\druntime\import


I'm using a Windows 11 machine so I thought that maybe the 
syntax was for Linux environment. But replacing all the '/' 
with '\' did not work.


An easier fix may be perhaps to just use 'dub' and install the 
glfw dependency. In my talk, I did everything from scratch (my 
preferred way), though I suspect using dub with glfw-d 
(https://code.dlang.org/packages/glfw-d) may provide less 
resistance.


Re: Boneheaded question regarding compilation...

2024-04-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 1 April 2024 at 21:23:50 UTC, WhatMeWorry wrote:


Huge fan of Mike Shah's YouTube videos regarding D and his 
latest for D conference:


https://mshah.io/conf/24/DConf%20%20Online%202024%20_%20The%20Case%20for%20Graphics%20Programming%20in%20Dlang.pdf

So I installed github desktop app and cloned his Talks repo. 
There is a build command commented out at the top of the main.d 
file which I've been trying to compile, via the command line:


C:\Users\kheas\Documents\Talks\2024\dconf_online\hello_triangle>dmd -g -J. main.d 
./glad/gl/*.d -L-L/usr/local/lib -L-lglfw3 -of=prog && ./prog
Error: cannot find input file `.\glad\gl\*.d`
import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos
import path[1] = 
C:\D\dmd2\windows\bin64\..\..\src\druntime\import


I'm using a Windows 11 machine so I thought that maybe the 
syntax was for Linux environment. But replacing all the '/' 
with '\\' did not work.


Those are indeed Linux parameters and not windows compatible. 
This can’t be fixed by switching slash styles.


You need the appropriate libs and the appropriate linker switches.

-Steve


Boneheaded question regarding compilation...

2024-04-01 Thread WhatMeWorry via Digitalmars-d-learn



Huge fan of Mike Shah's YouTube videos regarding D and his latest 
for D conference:


https://mshah.io/conf/24/DConf%20%20Online%202024%20_%20The%20Case%20for%20Graphics%20Programming%20in%20Dlang.pdf

So I installed github desktop app and cloned his Talks repo. 
There is a build command commented out at the top of the main.d 
file which I've been trying to compile, via the command line:


C:\Users\kheas\Documents\Talks\2024\dconf_online\hello_triangle>dmd -g -J. main.d 
./glad/gl/*.d -L-L/usr/local/lib -L-lglfw3 -of=prog && ./prog
Error: cannot find input file `.\glad\gl\*.d`
import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos
import path[1] = C:\D\dmd2\windows\bin64\..\..\src\druntime\import

I'm using a Windows 11 machine so I thought that maybe the syntax 
was for Linux environment. But replacing all the '/' with '\' did 
not work.





Re: Question on shared memory concurrency

2024-03-05 Thread Andy Valencia via Digitalmars-d-learn

On Monday, 4 March 2024 at 18:08:52 UTC, Andy Valencia wrote:
For any other newbie dlang voyagers, here's a version which 
works as expected using the system memory allocator.  On my 
little i7 I get 1.48 secs wallclock with 5.26 CPU seconds.

...


Using a technique I found in a unit test in std/concurrency.d, I 
managed to share process memory without GC.  It counted up to 
1,000,000,000 on my low end i7 in:


real0m15.666s
user0m59.913s
sys 0m0.004s



import core.atomic : atomicFetchAdd;
import std.concurrency : spawn, send, receiveOnly, ownerTid;
import core.thread : Thread;

const uint NSWEPT = 1_000_000_000;
const uint NCPU = 4;

void
doadd()
{
auto val = receiveOnly!(shared(int)[]);
for (uint count = 0; count < NSWEPT/NCPU; ++count) {
atomicFetchAdd(val[0], 1);
}
ownerTid.send(true);
}

void
main()
{
static shared int[] val = new shared(int)[1];

// Parallel workers
for (int x = 0; x < NCPU; ++x) {
auto tid = spawn();
tid.send(val);
}

// Pick up all completed workers
for (int x = 0; x < NCPU; ++x) {
receiveOnly!(bool);
}
assert(val[0] == NSWEPT);
}




Re: Question on shared memory concurrency

2024-03-04 Thread Andy Valencia via Digitalmars-d-learn

On Monday, 4 March 2024 at 16:02:50 UTC, Andy Valencia wrote:
On Monday, 4 March 2024 at 03:42:48 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
... I still hope to be able to share memory between spawned 
threads, and if it isn't a shared ref of a shared variable, 
then what would it be?  Do I have to use the memory allocator?


For any other newbie dlang voyagers, here's a version which works 
as expected using the system memory allocator.  On my little i7 I 
get 1.48 secs wallclock with 5.26 CPU seconds.




import core.atomic : atomicFetchAdd;
import std.concurrency : spawn;
import core.time : msecs;
import core.thread : Thread;
import core.memory : GC;

const uint NSWEPT = 100_000_000;
const uint NCPU = 4;

void
doadd(shared uint *buf)
{
for (uint count = 0; count < NSWEPT/NCPU; ++count) {
atomicFetchAdd(buf[0], 1);
}
}

void
main()
{
shared uint *buf =
cast(shared uint *)GC.calloc(uint.sizeof * 1, 
GC.BlkAttr.NO_SCAN);


for (uint x = 0; x < NCPU-1; ++x) {
spawn(, buf);
}
doadd(buf);
while (buf[0] != NSWEPT) {
Thread.sleep(1.msecs);
}
}


Re: Question on shared memory concurrency

2024-03-04 Thread evilrat via Digitalmars-d-learn

On Monday, 4 March 2024 at 16:02:50 UTC, Andy Valencia wrote:
On Monday, 4 March 2024 at 03:42:48 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

A way to do this without spawning threads manually:
...


Thank you!  Of course, a thread dispatch per atomic increment 
is going to be s.l.o.w., so not surprising you had to trim the 
iterations.


Bug I still hope to be able to share memory between spawned 
threads, and if it isn't a shared ref of a shared variable, 
then what would it be?  Do I have to use the memory allocator?


There is `__gshared` type qualifier, but unlike plain `shared` it 
is up to you to ensure valid concurrency access as stated in the 
docs.


https://dlang.org/spec/const3.html#shared_global


Re: Question on shared memory concurrency

2024-03-04 Thread Andy Valencia via Digitalmars-d-learn
On Monday, 4 March 2024 at 03:42:48 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

A way to do this without spawning threads manually:
...


Thank you!  Of course, a thread dispatch per atomic increment is 
going to be s.l.o.w., so not surprising you had to trim the 
iterations.


Bug I still hope to be able to share memory between spawned 
threads, and if it isn't a shared ref of a shared variable, then 
what would it be?  Do I have to use the memory allocator?


Re: Question on shared memory concurrency

2024-03-03 Thread Richard (Rikki) Andrew Cattermole via Digitalmars-d-learn

A way to do this without spawning threads manually:

```d
import std.parallelism : TaskPool, parallel, taskPool, defaultPoolThreads;
import std.stdio : writeln;
import std.range : iota;

enum NSWEPT = 1_000_000;
enum NCPU = 4;

void main() {
import core.atomic : atomicLoad, atomicOp;

shared(uint) value;

defaultPoolThreads(NCPU);
TaskPool pool = taskPool();

foreach(_; pool.parallel(iota(NSWEPT))) {
atomicOp!"+="(value, 1);
}

writeln(pool.size);
writeln(atomicLoad(value));
}
```

Unfortunately I could only use the default task pool, creating a new one 
took too long on run.dlang.io.


I also has to decrease NSWEPT because anything larger would take too long.


Question on shared memory concurrency

2024-03-03 Thread Andy Valencia via Digitalmars-d-learn
I tried a shared memory parallel increment.  Yes, it's basically 
a cache line thrasher, but I wanted to see what's involved in 
shared memory programming.  Even though I tried to follow all the 
rules to make true shared memory (not thread local) it appears I 
failed, as the wait loop at the end only sees its own local 250 
million increments?


import core.atomic : atomicFetchAdd;
import std.stdio : writeln;
import std.concurrency : spawn;
import core.time : msecs;
import core.thread : Thread;

const uint NSWEPT = 1_000_000_000;
const uint NCPU = 4;

void
doadd(ref shared(uint) val)
{
for (uint count = 0; count < NSWEPT/NCPU; ++count) {
atomicFetchAdd(val, 1);
}
}

void
main()
{
shared(uint) val = 0;

for (int x = 0; x < NCPU-1; ++x) {
spawn(, val);
}
doadd(val);
while (val != NSWEPT) {
Thread.sleep(1.msecs);
}
}


question about ctfe init importC zero length array of struct

2024-02-28 Thread Dakota via Digitalmars-d-learn

This is the type defined from c code import by importC:


```c
struct A {
   int count;
   int[] i;
}
```

This kind data need to be init as const to avoid runtime cost, 
and need to be done from D code.



how can I do this ?


To put code into D source,  I can use "-i=package" to 
automatically import the only need part without rebuild it, and 
avoid the problem of importC path search. (and there is type 
wrapper inside D code).


I can fix it with a template type, the cost is very slow build 
time. (because there is a lot diff auto generate type)



Any suggestions how to handle this fast and simple ?





Re: question

2023-12-13 Thread Adam D Ruppe via Digitalmars-d-learn

On Wednesday, 13 December 2023 at 12:49:14 UTC, fred wrote:

a bug ?


It helps if you explain what you're talking about so we don't 
have to guess.


I tried the code on my computer and it worked fine. But then 
figuring, you must be saying something doesn't work right, I 
tried it on another compiler and saw it endlessly loop.


So it ended using my dmd 2.098, looped on my dmd 2.105 but 
this is actually just coincidence. Consider this:


---
void s2()
{
shared(bool) isDone = false;
spawn(, );
Thread.sleep(400.msecs);
w("done");
isDone = true;
}
---

The variable `isDone` is temporary; as a local variable, it 
ceases to exist when s2 returns. So when w2 tries to check if it 
is done or not, it takes a bit of luck for the memory to still be 
the same value as it was; it has likely been recycled or 
otherwise cleared by then.


You need to keep the variable alive until *both* threads are done 
with it, either by doing some fancy synchronization between the 
threads or just letting the garbage collector manage the shared 
variable:



```
void s2()
{
 // let the GC do it
shared(bool)* isDone = new shared bool;
spawn(, isDone);
Thread.sleep(400.msecs);
w("done");
*isDone = true;
}
```


Re: question

2023-12-13 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 13 December 2023 at 12:49:14 UTC, fred wrote:

[...]
a bug ?
thanks anyway


Try to define the flag as static

```d
static shared(bool) isDone = false;
```

I dont know if that should be a compiler error to have local 
shared (I tend to think yes as locals are specific to a frame, 
i.e a thread). At least you know how to fix the issue.




question

2023-12-13 Thread fred via Digitalmars-d-learn

import core.thread;
import std.concurrency;
import std.stdio : w = writeln;

void w2(shared(bool) *done)
{
while (*done == false)
{
Thread.sleep(100.msecs);
w("print done? ", *done);
}
}

void s2()
{
shared(bool) isDone = false;
spawn(, );
Thread.sleep(400.msecs);
isDone = true;

}

void main()
{
s2();
}

=

a bug ?
thanks anyway


Re: 'typeof' question

2023-11-28 Thread DLearner via Digitalmars-d-learn

On Tuesday, 28 November 2023 at 18:43:37 UTC, Adam D Ruppe wrote:

On Tuesday, 28 November 2023 at 18:41:49 UTC, DLearner wrote:

A* A_Ptr;

struct B {
   int BFld2;
   typeof(A_Ptr)[0..($-1)] ASUB; // Idea is ASUB of type A, 
from A_Ptr of type A*.



I think what you really want is

typeof(*A_Ptr) ASUB;


the typeof thing returns the type you'd get from the code inside


Thanks - worked.


Re: 'typeof' question

2023-11-28 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 28 November 2023 at 18:41:49 UTC, DLearner wrote:

A* A_Ptr;

struct B {
   int BFld2;
   typeof(A_Ptr)[0..($-1)] ASUB; // Idea is ASUB of type A, 
from A_Ptr of type A*.



I think what you really want is

typeof(*A_Ptr) ASUB;


the typeof thing returns the type you'd get from the code inside


'typeof' question

2023-11-28 Thread DLearner via Digitalmars-d-learn
Trying to manipulate 'typeof' return strings, preferably at 
compile-time.


e.g. to produce struct B below (intended to have an A 
sub-struct), from A_Ptr alone.

```
struct A {
   int AFld1;
}
A* A_Ptr;

struct B {
   int BFld2;
   typeof(A_Ptr)[0..($-1)] ASUB; // Idea is ASUB of type A, from 
A_Ptr of type A*.

}
```
But this fails with 'can only slice tuple types...'.

Suggestions?



Re: Question regarding mir.csv.

2023-11-01 Thread Sergey via Digitalmars-d-learn

On Wednesday, 1 November 2023 at 20:49:16 UTC, Zz wrote:

Hi,

Currently using std.csv and would like to do the following 
using mir.csv.


auto data = std.csv.csvReader!Layout(input).array;

Are there any examples out there on using mir.csv?

Regards,
Zz


you can find some examples in source code:
https://github.com/libmir/mir-ion/blob/master/source/mir/csv.d


Question regarding mir.csv.

2023-11-01 Thread Zz via Digitalmars-d-learn

Hi,

Currently using std.csv and would like to do the following using 
mir.csv.


auto data = std.csv.csvReader!Layout(input).array;

Are there any examples out there on using mir.csv?

Regards,
Zz


Re: Question about interface implementation

2023-05-21 Thread Theo via Digitalmars-d-learn

On Sunday, 21 May 2023 at 11:20:30 UTC, ag0aep6g wrote:

On 21.05.23 12:55, Theo wrote:
As for the other part, if I use an abstract base class, I 
*must* indicate when i'm overriding the base class method by 
explicately saying 'override'.


I wouldn't mind if implementing interface methods required 
`override` as well. I don't know if there is a rationale for 
the inconsistency.


Consistency, which can also aid in self-documenting, might look 
something like this:


- using interface -

interface Ship
{
void setSpeed(int speed); // must 'implement'
int getSpeed(); // must 'implement'
}

class PirateShip : Ship
{
private(this) int speed = 0;

public void setSpeed(int speed) : implements Ship
{
this.speed = speed;
}

public int getSpeed() : implements Ship
{
return speed;
}
}

- using base class -
abstract base class Ship
{
abstract void setSpeed(int speed); // must 'implement'
abstract int getSpeed(); // must 'implement'
void someotherMethod(); // can 'override'.
}

class PirateShip : Ship
{
private(this) int speed = 0;

public void setSpeed(int speed) : implements Ship
{
this.speed = speed;
}

public int getSpeed() : implements Ship
{
return speed;
}

public void someotherMethod() : overrides Ship
{

}
}

-



Re: Question about interface implementation

2023-05-21 Thread ag0aep6g via Digitalmars-d-learn

On 21.05.23 12:55, Theo wrote:
As for the other part, if I use an abstract base class, I *must* 
indicate when i'm overriding the base class method by explicately saying 
'override'.


I wouldn't mind if implementing interface methods required `override` as 
well. I don't know if there is a rationale for the inconsistency.




Re: Question about interface implementation

2023-05-21 Thread Theo via Digitalmars-d-learn

On Sunday, 21 May 2023 at 10:33:07 UTC, ag0aep6g wrote:

On 21.05.23 12:28, ag0aep6g wrote:
Since @trusted functions are guaranteed (by the programmer) to 
be safe, they are allowed to overload/implement @safe 
functions/prototypes.


*override


oh ok. so i can override a @safe interface method with a @trusted 
implementation of that method, and nobody will ever know. I'm not 
sure how i feel about that.


Likely I would never put @safe in the interface anyway, but even 
so...


As for the other part, if I use an abstract base class, I *must* 
indicate when i'm overriding the base class method by explicately 
saying 'override'.


Would be nice to have something for an interface method, so when 
it's being implemented, you know that method is the 
implementation of an interface method, and not just some method 
specific to that class - see my idea below.


interface Ship
{
void setSpeed(int speed);
int getSpeed();
}

class PirateShip : Ship
{
private int speed = 0; // Here, I really mean 'private(this)'

public void setSpeed(int speed) : implements Ship
{
this.speed = speed;
}

public int getSpeed() : implements Ship
{
return speed;
}
}

// other ships.



Re: Question about interface implementation

2023-05-21 Thread ag0aep6g via Digitalmars-d-learn

On 21.05.23 12:28, ag0aep6g wrote:
Since @trusted functions are guaranteed (by the programmer) 
to be safe, they are allowed to overload/implement @safe 
functions/prototypes.


*override


Re: Question about interface implementation

2023-05-21 Thread ag0aep6g via Digitalmars-d-learn

On 21.05.23 11:55, Theo wrote:

class MerchantShip : Ship
{
     private int speed = 0; // If only I had 'private(this)' !!

     // how do I know this method is actually an implementation of an 
interface method

     // and not a method specific to this class?
     // AND ... how come I can change a @safe interface method into a 
@trusted one?

     public @trusted void setSpeed(int speed)
     {
     int *s = void; // Mmmm.. and my interface all had @safe methods!!
     this.speed = speed;
     }

[...]

}


As far as I understand, a method that has the right signature is always 
an implementation of the interface. There is no way to make a method of 
the same name, with the same parameters, etc. that is "specific to the 
class".


@trusted means that you're allowed to use @system features in the 
implementation while the function must follow the restrictions of @safe 
when called. Since @trusted functions are guaranteed (by the programmer) 
to be safe, they are allowed to overload/implement @safe 
functions/prototypes.


If you create an @trusted function that is not safe to call, that's an 
error on your part.


Question about interface implementation

2023-05-21 Thread Theo via Digitalmars-d-learn

see comments in the code below. they are my questions.

But feel free to ignore the comment about 'private(this)' ;-)


interface Ship
{
@safe void setSpeed(int speed);
@safe int getSpeed();
}

class PirateShip : Ship
{
private int speed = 0; // If only I had 'private(this)' !!

// how do I know this method is actually an implementation of 
an interface method

// and not a method specific to this class?
public void setSpeed(int speed)
{
this.speed = speed;
}

   // how do I know this method is actually an implementation of 
an interface method

   // and not a method specific to this class?
   public int getSpeed()
{
return speed;
}
}


class MerchantShip : Ship
{
private int speed = 0; // If only I had 'private(this)' !!

// how do I know this method is actually an implementation of 
an interface method

// and not a method specific to this class?
// AND ... how come I can change a @safe interface method 
into a @trusted one?

public @trusted void setSpeed(int speed)
{
int *s = void; // Mmmm.. and my interface all had @safe 
methods!!

this.speed = speed;
}

// how do I know this method is actually an implementation of 
an interface method

// and not a method specific to this class?
// AND ... how come I can change a @safe interface method 
into a @trusted one?

public @trusted int getSpeed()
{
int *s = void; // Mmmm.. and my interface all had @safe 
methods!!

return speed;
}

}



Re: quick question, probably of little importance...

2023-04-30 Thread Cecil Ward via Digitalmars-d-learn

On Monday, 1 May 2023 at 03:53:24 UTC, Cecil Ward wrote:

On Wednesday, 26 April 2023 at 23:07:39 UTC, WhatMeWorry wrote:

[...]




Correction: I can’t count. There are only two instructions in 
parallel with another pair running alongside, not three. The 
first reg, reg move counts as zero cycles, so the total time is 
just the sum of the following three instructions’ times, ignoring 
the other parallel stream.


Re: quick question, probably of little importance...

2023-04-30 Thread Cecil Ward via Digitalmars-d-learn

On Wednesday, 26 April 2023 at 23:07:39 UTC, WhatMeWorry wrote:
On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) 
Andrew Cattermole wrote:

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers 
within the last 30 years should recognize all forms of this 
and do the right thing.


Thanks. Fastest reply ever! And I believe across the world?   I 
suppose my examples required overhead of a function call. So 
maybe num % 2 == 0 is fastest?


I made a small change, making the retval a bool rather than an 
int. I got slightly better code generation with the int, as it 
seems that some of the compilers have not yet got all the good 
tricks they should be using when manipulating bool-typed 
expressions and also it can be one extra instruction converting 
values to bool strictly zero or one, not zero or any non-zero 
value. Here’s the D, enlarged a little so that we can see your 
routine in action, inlined. Your isEven boils down to two 
instructions with a seriously optimising compiler. I’ve included 
the x86-64 machine code generated by the GDC and LDC compilers so 
you can see how fast it is. GDC made a bit of a dog’s breakfast 
of my longer routine whereas LDC performed superbly. GDC 
generated twice as much code, but its excellent instruction 
scheduler and what looks like an awareness of ILP mean that the 
two streams of instructions will be carried out in parallel  so 
the two streams will only take three instruction times - ie 
whatever the total time is for those three instruction in the one 
stream - not six.


bool isEven( int num )
{
return ! ( num & 1 );
}

bool AreBothEven( int a, int b )  // returns true if both 
arguments are even

{
return isEven( a )  &&  isEven( b );
}

===
Compiler output:: GDC:: x86-64: -O3 -mcpu=native -frelease

bool isEven( int ):
mov eax, edi
not eax
and eax, 1
ret

bool AreBothEven( int, int ):
mov eax, edi
not esi
not eax
and esi, 1
and eax, 1
cmovne  eax, esi
ret

===
Compiler LDC: x86-64: -O3 -mcpu=native -release

bool isEven( int ):
testdil, 1
seteal
ret

bool AreBothEven( int, int ):
or  edi, esi
testdil, 1
seteal
ret


Re: quick question, probably of little importance...

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

On 27/04/2023 11:07 AM, WhatMeWorry wrote:
On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers within the 
last 30 years should recognize all forms of this and do the right thing.


Thanks. Fastest reply ever! And I believe across the world?   I suppose 
my examples required overhead of a function call. So maybe num % 2 == 0 
is fastest?


Indeed, all the way from New Zealand.

I wouldn't bother timing this. A compiler will rewrite it and emit 
whatever instructions it thinks is best for a given cpu target that you 
select. This is one of those things that was solved 30 years ago :)


Re: quick question, probably of little importance...

2023-04-26 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Apr 26, 2023 at 11:07:39PM +, WhatMeWorry via Digitalmars-d-learn 
wrote:
> On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) Andrew
> Cattermole wrote:
> > Don't forget ``num % 2 == 0``.
> > 
> > None should matter, pretty much all production compilers within the
> > last 30 years should recognize all forms of this and do the right
> > thing.
> 
> Thanks. Fastest reply ever! And I believe across the world?   I
> suppose my examples required overhead of a function call. So maybe num
> % 2 == 0 is fastest?

If performance matters, you'd be using an optimizing compiler. And
unless you're hiding your function implementation behind a .di, almost
all optimizing compilers would inline it, so you shouldn't even be able
to tell the difference.


T

-- 
Without outlines, life would be pointless.


Re: quick question, probably of little importance...

2023-04-26 Thread WhatMeWorry via Digitalmars-d-learn
On Wednesday, 26 April 2023 at 23:02:07 UTC, Richard (Rikki) 
Andrew Cattermole wrote:

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers within 
the last 30 years should recognize all forms of this and do the 
right thing.


Thanks. Fastest reply ever! And I believe across the world?   I 
suppose my examples required overhead of a function call. So 
maybe num % 2 == 0 is fastest?


Re: quick question, probably of little importance...

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

Don't forget ``num % 2 == 0``.

None should matter, pretty much all production compilers within the last 
30 years should recognize all forms of this and do the right thing.


quick question, probably of little importance...

2023-04-26 Thread WhatMeWorry via Digitalmars-d-learn
I just need an even/odd functionality. Don't think D has a 
built-in operator.


// Found this C code online.

int isEven(int num)
{
return !(num & 1);
}

// found this in std.functional.unaryFun

alias isEven = unaryFun!("(a & 1) == 0");
assert(isEven(2) && !isEven(1));

If interested just in speed, is either one faster?


Re: (Noob question) Should subclasses be defined in separate modules?

2023-01-12 Thread Mike Parker via Digitalmars-d-learn
On Friday, 13 January 2023 at 05:17:59 UTC, thebluepandabear 
wrote:

(Sorry if this is a duplicate.)

If I have the following code inside of a module:

```D
class Obj {
private {
string name = "Hi";
}
}

class ObjDerived : Obj {

}
```

Is it best practice to define `ObjDerived` inside another 
module, since `ObjDerived` can still access the members of 
`Obj` (since `private` is only applied to modules), or does 
this go against the intended use of the language?


As a beginner, I am having an extremely tough time 
understanding why you would want to place these two classes in 
the same module or even have this intended behavior of 
`private`. I am coming from Java/Kotlin which are both strictly 
OO language and have different ways of encapsulation.


The short answer: just think of a module as a way of grouping 
related objects and functions. If it makes sense to you for 
`ObjDerived` to have access to the internals of `Obj`, then keep 
them in the same module. If it doesn't, then put it somewhere 
else.


The long answer: there's no one-size-fits all here. For a short 
program, a script let's say, just dump everything in one module 
and be done with it. For a program you're writing for your own 
use, do whatever you feel comfortable with, even if you plan to 
open source it.


For something you're writing for others to use, like a library, 
then the first priority is to think about what the public facing 
API should look like. From that perspective, does `ObDerived` 
belong in the same module, or is it unrelated enough to go into a 
different one?


If it does fit in the same module, then that can be enough. It is 
for me. I'd stop there. But some people want to go one step 
further and ensure that `ObjDerived` can't access the internals 
of `Obj`. So in that case, you can put them in two separate 
modules and make a `package.d` file to act as the common module 
name for both. I think there are good reasons to do that, but 
most of the time it's just a matter of preference.





(Noob question) Should subclasses be defined in separate modules?

2023-01-12 Thread thebluepandabear via Digitalmars-d-learn

(Sorry if this is a duplicate.)

If I have the following code inside of a module:

```D
class Obj {
private {
string name = "Hi";
}
}

class ObjDerived : Obj {

}
```

Is it best practice to define `ObjDerived` inside another module, 
since `ObjDerived` can still access the members of `Obj` (since 
`private` is only applied to modules), or does this go against 
the intended use of the language?


As a beginner, I am having an extremely tough time understanding 
why you would want to place these two classes in the same module 
or even have this intended behavior of `private`. I am coming 
from Java/Kotlin which are both strictly OO language and have 
different ways of encapsulation.





Re: auto scope question?

2022-10-25 Thread WhatMeWorry via Digitalmars-d-learn



typeof(screen.output.findSplit("")) s;


Perfect. That was the "essence" of my question. But thanks to 
Ali, I don't have to use such esoteric syntax.  D is a wonderful 
language, but I seem to shoot myself in the foot :)


Re: auto scope question?

2022-10-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/25/22 6:07 PM, WhatMeWorry wrote:
I'm naturally getting a undefined identifier `s` error in the return.  
Is there some way to refactor my code?  I tried to declare s outside of 
the else brackets like:


auto screen = executeShell(cmdLine);
auto s;
...
{
     s = screen.output.findSplit("REG_SZ");
}

but that doesn't compile either.



string[] getPath(string cmdLine)
{
     auto screen = executeShell(cmdLine);

     if (screen.status != 0)
     {
     writeln(cmdLine, " failed");
     }
     else
     {
     writeln("screen.output = ", screen.output);
 auto s = screen.output.findSplit("REG_SZ");
     writeln("s[0] = ", s[0]);
     writeln("s[1] = ", s[1]);
     writeln("s[2] = ", s[2]);
     }
     return (s.split(';'));  // Error: undefined identifier `s`
}


As Ali mentioned, your logic is faulty -- you seem to write that the 
command failed, but then return something anyway.


Also, you are returning `string[]`, so just declaring `string[] s;` 
should be enough.


However, I did want to mention that if you do want to hoist a difficult 
to name type outside where it is declared with an auto, you can use 
`typeof`:


```d
typeof(screen.output.findSplit("")) s;
```

In this case, it's just `string[]`, but the idea here is you can name a 
type without naming it, by using `typeof` on the expression you would 
have called.


Hope this helps further your D knowledge ;)

-Steve


Re: auto scope question?

2022-10-25 Thread Ali Çehreli via Digitalmars-d-learn

On 10/25/22 15:07, WhatMeWorry wrote:

> auto screen = executeShell(cmdLine);
> auto s;

That can't work because there is no information to infer the type of 
's'. Judging from the return type of getPath, perhaps it's string[]:


string[] s;

This is the question we should answer first: What should happen when 
executeShell fails?


a) It is an error; the program should not continue. Then we can use 
'enforce' (this is my way of coding):


string[] getPath(string cmdLine)
{
import std.exception : enforce;

auto screen = executeShell(cmdLine);
enforce(screen.status == 0, format!"%s failed:\n%s"(cmdLine, 
screen.output));


writeln("screen.output = ", screen.output);
auto s = screen.output.findSplit("REG_SZ");
writeln("s[0] = ", s[0]);
writeln("s[1] = ", s[1]);
writeln("s[2] = ", s[2]);

return (s.split(';'));
}

b) It is not an error; getPath() should return empty array:

string[] getPath(string cmdLine)
{
string[] result;
auto screen = executeShell(cmdLine);

if (screen.status != 0)
{
writeln(cmdLine, " failed");
return null;  // <-- HERE (null converts to any array type)
}
else
{
// ...
// Now, 'return' is where 's' is defined:
return (s.split(';'));
}
}

Ali



auto scope question?

2022-10-25 Thread WhatMeWorry via Digitalmars-d-learn
I'm naturally getting a undefined identifier `s` error in the 
return.  Is there some way to refactor my code?  I tried to 
declare s outside of the else brackets like:


auto screen = executeShell(cmdLine);
auto s;
...
{
s = screen.output.findSplit("REG_SZ");
}

but that doesn't compile either.



string[] getPath(string cmdLine)
{
auto screen = executeShell(cmdLine);

if (screen.status != 0)
{
writeln(cmdLine, " failed");
}
else
{
writeln("screen.output = ", screen.output);   
auto s = screen.output.findSplit("REG_SZ");
writeln("s[0] = ", s[0]);
writeln("s[1] = ", s[1]);
writeln("s[2] = ", s[2]); 
}
return (s.split(';'));  // Error: undefined identifier `s`
}


Re: Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread matheus via Digitalmars-d-learn

On Sunday, 23 October 2022 at 17:36:25 UTC, Paul Backus wrote:

On Sunday, 23 October 2022 at 13:32:44 UTC, matheus wrote:

...


You say your idea is "like passing some argument", so why not 
actually pass an argument?


For example:
...


Hi, thanks for the example, and yes I'd like to do that, but I'm 
looking for this "chaining"  things which seems to be some sort 
of pattern these days.


Like I said to Sergey, I think I'll use the library as example, 
except that I think that I'd do the otherwise, calling just 
"sort()" would give a duplicate, and chaining with "save()", 
"inplace()" or whatever name is would sort in place (Caller).


Thanks,

Matheus.




Re: Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread matheus via Digitalmars-d-learn

On Sunday, 23 October 2022 at 16:16:55 UTC, Sergey wrote:

On Sunday, 23 October 2022 at 15:47:27 UTC, matheus wrote:

Hi H. S. Teoh,

I think you misunderstood my question, since English is not my 
first language maybe this was a problem from my part, but 
anyway, I'm not talking about "sort" from main library.


This example was if I had designed my "own version".

Matheus.


Hi, Matheus. I'm not an expert in programming :)
But I believe it should be up to you. How you make your 
function...


Hi, yes I know but I'd like to know what is the most "common way" 
of doing this. I think I'll use the library as example, except 
that I think that I'd do otherwise, calling "sort()" would give a 
duplicate, and chaining with "save()" or "inplace()" would sort 
the caller.


Thanks,

Matheus.


Re: Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 23 October 2022 at 13:32:44 UTC, matheus wrote:
I have a design question and I'd like to hear some advice. 
Let's say that I want to create a method to sort an array:


arr.sort(asc);

I think usually this would usually return a new set of that 
array but now sorted.


But If I want to do this in the original, I think I would do 
this:


arr.sort(asc).save();

The problem with this, it would create a new set and 
assign/copy back to the caller, which would be a waste. So I 
thought about this:


arr.save.sort(asc);

Then save would tell to "sort()" what to do beforehand, like 
passing some argument saying that the sort should be done 
direct in the caller and no copy.


Is this (The latter) an approach you would use? Or there is a 
better way to do this.


You say your idea is "like passing some argument", so why not 
actually pass an argument?


For example:

enum Direction { asc, desc }
enum InPlace : bool { no, yes }

ref Arr sort(ref Arr arr, Direction dir, InPlace inPlace = 
InPlace.no)

{
if (inPlace) {
arr.sortInPlace(dir);
return arr;
} else {
return arr.sortedCopy(dir);
}
}

Usage would look like this:

auto sorted = arr.sort(asc); // sorted copy
arr.sort(desc, InPlace.yes); // sort in place


Re: Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread Sergey via Digitalmars-d-learn

On Sunday, 23 October 2022 at 15:47:27 UTC, matheus wrote:

Hi H. S. Teoh,

I think you misunderstood my question, since English is not my 
first language maybe this was a problem from my part, but 
anyway, I'm not talking about "sort" from main library.


This example was if I had designed my "own version".

Matheus.


Hi, Matheus. I'm not an expert in programming :)
But I believe it should be up to you. How you make your function.
If you will use "ref" in the parameter - you could operates 
exactly the same memory which will received in the parameter;
Also there are 'in','out', 'inout' parameters that could help 
with management on that question.


Re: Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread matheus via Digitalmars-d-learn

Hi H. S. Teoh,

I think you misunderstood my question, since English is not my 
first language maybe this was a problem from my part, but anyway, 
I'm not talking about "sort" from main library.


This example was if I had designed my "own version".

Matheus.


Re: Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Oct 23, 2022 at 01:32:44PM +, matheus via Digitalmars-d-learn wrote:
> Hi,
> 
> I have a design question and I'd like to hear some advice. Let's say
> that I want to create a method to sort an array:
> 
> arr.sort(asc);
> 
> I think usually this would usually return a new set of that array but
> now sorted.

No, it does not.  It sorts `arr` in-place.


> But If I want to do this in the original, I think I would do this:
> 
> arr.sort(asc).save();

That's not necessary, the .save is completely redundant.


[...]
> By the way in this design I'd like to have both options, return a new
> set and/or change the original.

If you want a new sorted array without touching the original, do this
instead:

auto sortedArr = arr.dup.sort();


T

-- 
They say that "guns don't kill people, people kill people." Well I think the 
gun helps. If you just stood there and yelled BANG, I don't think you'd kill 
too many people. -- Eddie Izzard, Dressed to Kill


Design question regarding saving changes in the original array and/or returning a new set

2022-10-23 Thread matheus via Digitalmars-d-learn

Hi,

I have a design question and I'd like to hear some advice. Let's 
say that I want to create a method to sort an array:


arr.sort(asc);

I think usually this would usually return a new set of that array 
but now sorted.


But If I want to do this in the original, I think I would do this:

arr.sort(asc).save();

The problem with this, it would create a new set and assign/copy 
back to the caller, which would be a waste. So I thought about 
this:


arr.save.sort(asc);

Then save would tell to "sort()" what to do beforehand, like 
passing some argument saying that the sort should be done direct 
in the caller and no copy.


Is this (The latter) an approach you would use? Or there is a 
better way to do this.


By the way in this design I'd like to have both options, return a 
new set and/or change the original.


Thanks in advance,

Matheus.


Re: Real simple question... for good programmers

2022-10-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/22/22 5:53 PM, WhatMeWorry wrote:



string[] tokens = userSID.output.split!isWhite;
writeln("tokens = ", tokens);

tokens = ["SID", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"S-1-5-21-3823976785-3597194045-4221507747-1779", "", "", "", "", "", 
"", "", ""]



Is there a clever way that I can discard all the extra null strings in 
the resultant string array?


I've been playing with isControl, whitespace, etc. Ready to rip my hair 
out.


Try just split without the `isWhite`. If you look at the docs, you will see:

"When no delimiter is provided, strings are split into an array of 
words, using whitespace as delimiter. Runs of whitespace are merged 
together (no empty words are produced)."


-Steve



Re: Real simple question... for good programmers

2022-10-22 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 22 October 2022 at 21:53:05 UTC, WhatMeWorry wrote:



string[] tokens = userSID.output.split!isWhite;
writeln("tokens = ", tokens); 

[...]
Is there a clever way that I can discard all the extra null 
strings in the resultant string array?


Easiest way is to use [`filter`][1]. Here's an example:

```d
import std.algorithm: splitter, filter;
import std.uni: isWhite; // or use std.ascii for non-unicode input
import std.array: array;
import std.stdio: writeln;

string exampleText =
"Hello   123-456-ABCx\ny\tz\r\nwvu   goodbye";

void main()
{
string[] tokens = exampleText
.splitter!isWhite
.filter!(t => t.length > 0)
.array;
writeln("tokens = ", tokens);
}
```

I've also used the lazily-evaluated [`splitter`][2] instead of 
the eagerly-evaluated `split`, to avoid allocating a temporary 
array unnecessarily.


[1]: 
https://phobos.dpldocs.info/std.algorithm.iteration.filter.html
[2]: 
https://phobos.dpldocs.info/std.algorithm.iteration.splitter.3.html


Re: Real simple question... for good programmers

2022-10-22 Thread Daniel via Digitalmars-d-learn

On Saturday, 22 October 2022 at 22:01:09 UTC, Enjoys Math wrote:

On Saturday, 22 October 2022 at 21:53:05 UTC, WhatMeWorry wrote:



string[] tokens = userSID.output.split!isWhite;
writeln("tokens = ", tokens); 

tokens = ["SID", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", 
"S-1-5-21-3823976785-3597194045-4221507747-1779", "", "", "", 
"", "", "", "", ""]	



Is there a clever way that I can discard all the extra null 
strings in the resultant string array?


I've been playing with isControl, whitespace, etc. Ready to 
rip my hair out.




Why not `strip`?  Works on ranges:
https://dlang.org/phobos/std_algorithm_mutation.html#.strip


Strip won't work because it only works on the beginning and ends 
of the range.  What you want is `remove`.  See my other MWE post.




Re: Real simple question... for good programmers

2022-10-22 Thread Enjoys Math via Digitalmars-d-learn

__MWE Code:__
```
module DlangForumsMWE;

import std.stdio;
import std.algorithm.mutation;

int main()
{
   //string[] tokens = userSID.output.split!isWhite;
   //writeln("tokens = ", tokens);

   auto tokens = ["SID", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "",
  "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "",
  "", "", "", 
"S-1-5-21-3823976785-3597194045-4221507747-1779", "", "", "", "", 
"", "", "", ""];


   writeln("Before:\n", tokens);

   writeln();
   tokens = tokens.remove!(x => x == "");
   writeln("After:\n", tokens);

   readln();
   return 0;
}
```

__Outputs:__
```
Before:
["SID", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "S-1-5-21-3823976785-3597194045-4221507747-1779", "", "", "", 
"", "", "", "", ""]


After:
["SID", "S-1-5-21-3823976785-3597194045-4221507747-1779"]
```




Re: Real simple question... for good programmers

2022-10-22 Thread Ali Çehreli via Digitalmars-d-learn

On 10/22/22 14:53, WhatMeWorry wrote:
>
>
> string[] tokens = userSID.output.split!isWhite;
> writeln("tokens = ", tokens);

Could you please show minimal compilable code that demonstrates the 
issue. I spent some time with some guesses but failed (to get my code to 
compile with std.array.split).


Ali

P.S. Sorry for also sending email.


Re: Real simple question... for good programmers

2022-10-22 Thread Enjoys Math via Digitalmars-d-learn

On Saturday, 22 October 2022 at 21:53:05 UTC, WhatMeWorry wrote:



string[] tokens = userSID.output.split!isWhite;
writeln("tokens = ", tokens); 

tokens = ["SID", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", 
"S-1-5-21-3823976785-3597194045-4221507747-1779", "", "", "", 
"", "", "", "", ""]	



Is there a clever way that I can discard all the extra null 
strings in the resultant string array?


I've been playing with isControl, whitespace, etc. Ready to rip 
my hair out.




Why not `strip`?  Works on ranges:
https://dlang.org/phobos/std_algorithm_mutation.html#.strip


Real simple question... for good programmers

2022-10-22 Thread WhatMeWorry via Digitalmars-d-learn




string[] tokens = userSID.output.split!isWhite;
writeln("tokens = ", tokens); 

tokens = ["SID", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
"", "", "", "S-1-5-21-3823976785-3597194045-4221507747-1779", "", 
"", "", "", "", "", "", ""]	



Is there a clever way that I can discard all the extra null 
strings in the resultant string array?


I've been playing with isControl, whitespace, etc. Ready to rip 
my hair out.





Re: probably a trivial question...

2022-10-13 Thread rassoc via Digitalmars-d-learn

On 10/14/22 01:43, WhatMeWorry via Digitalmars-d-learn wrote:

Does D provide any guidance as to what is preferred or are they identical for 
all intents and purposes?


You won't see a difference for this specific example since the split function 
supports character, string and even range separators. So, use what works best 
for your use case.

But here's the difference between them:

Single quotes are for singular characters, 'hello' won't compile while ';' and 
'\n' (escaped newline) will.

Double quotes are string literals, i.e. array of characters, which also allow escape 
sequences like "\r\n".

Back ticks, as well as r"...", are raw or wysiwyg ("what you see is what you 
get") strings, they do not support escape sequences. They are super useful for regex.

import std;
void main() {
writeln("ab\ncd");  // \n is recognized as a newline character
writeln(`ab\ncd`);  // `...` and r"..." are equivalent
writeln(r"ab\ncd");
}

will print:

ab
cd
ab\ncd
ab\ncd

More info here, if you are interested: 
https://dlang.org/spec/lex.html#string_literals


Re: probably a trivial question...

2022-10-13 Thread Ali Çehreli via Digitalmars-d-learn

Changing the order of lines...

On 10/13/22 16:43, WhatMeWorry wrote:

> return s.split(';');  // single quotes

That one is a single character and very lightweigth because it's just an 
integral value. You can't put more than one character within single quotes:


 ';x' // ERROR

> return s.split(";");  // double quotes

That one is a string, which is the equivalent of the following "fat 
pointer":


struct Array_ {
  size_t length;
  char * ptr;
}

For that reason, it can be seen as a little bit more costly. 'length' 
happens to be 1 but you can use multiple characters in a string:


  ";x" // works

(Aside: There is also a '\0' character sitting next to the ';' in memory 
so that the literal can be passed to C functions as-is.)


Double-quoted strings have the property of escaping. For example, "\n" 
is not 2 characters but is "the newline character".


> return s.split(`;`);  // back ticks

They are strings as well but they don't do escaping: `\n` happens to be 
2 characters.


There is also strings that start with q{ and end with }:

  auto myString = q{
  hello
  world
  };

And then there is delimited strings that use any delimiter you choose:

auto myString = q"MY_DELIMITER
hello
world
MY_DELIMITER";

Some information here:

  http://ddili.org/ders/d.en/literals.html#ix_literals.string%20literal

Ali




probably a trivial question...

2022-10-13 Thread WhatMeWorry via Digitalmars-d-learn



I was a little (nicely) surprised that I could use double quotes, 
single quotes, or back ticks in the following line of code.


return s.split(";");  // double quotes
or
return s.split(';');  // single quotes
or
return s.split(`;`);  // back ticks

Does D provide any guidance as to what is preferred or are they 
identical for all intents and purposes?


Re: Question on shapes

2022-05-18 Thread JG via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 00:10:55 UTC, Alain De Vos wrote:
Let's say a shape is ,a circle with a radius ,or a square with 
a rectangular size.
I want to pass shapes to functions, eg to draw them on the 
screen,

draw(myshape) or myshape.draw();
But how do i implement best shapes ?


You could also do something like:
```d
import std;

struct Circle {
double radius;
void draw() {
writeln(format!"Draw a circle of radius %s"(radius));
}
}

struct Rectangle {
double width;
double height;
 void draw() {
writeln(format!"Draw a rectangle of width %s and height 
%s."(width,height));

}
}

alias Shape = SumType!(Circle,Rectangle);


void main() {
  Shape[] shapes = [Shape(Rectangle(2.0,3.)),Shape(Circle(3.0))];

  foreach(shape; shapes) { shape.match!(x=>x.draw); }
}
```

or

```d
import std;

struct Circle {
double radius;
}

struct Rectangle {
double width;
double height;
}

alias Shape = SumType!(Circle,Rectangle);

struct Drawer {
int drawerState;
void drawShape(Shape shape) {
shape.match!(x=>drawShape(x));
}
void drawShape(Circle circle) {
writeln(format!"Draw a circle of radius 
%s"(circle.radius));

}
void drawShape(Rectangle rectangle) {
writeln(format!"Draw a rectangle of width %s and height 
%s."(rectangle.width,rectangle.height));

}
}

void main() {
  Shape[] shapes = [Shape(Rectangle(2.0,3.)),Shape(Circle(3.0))];
  Drawer d;
  foreach(shape; shapes) { d.drawShape(shape); }
}
```




Re: Question on shapes

2022-05-17 Thread Dom Disc via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 09:30:12 UTC, forkit wrote:

On Tuesday, 17 May 2022 at 04:37:58 UTC, Ali Çehreli wrote:




In you OOP example, I am curious why you chose Shape to be an 
interface, rather than a base class.


You can inherit from multiple interfaces, but only from one base 
class.
So if you need multiple inheritance, better use interfaces. 
Especially at the first level of objects I would almost always 
use only interfaces, no classes. I consider this better design.


Re: Question on shapes

2022-05-17 Thread Ali Çehreli via Digitalmars-d-learn

On 5/17/22 02:30, forkit wrote:
> On Tuesday, 17 May 2022 at 04:37:58 UTC, Ali Çehreli wrote:
>>
>
> In you OOP example, I am curious why you chose Shape to be an interface,
> rather than a base class.

I always have the same question. :) interface feels lighterweight, so it 
is an arbitrary decision for me. I haven't hit any situation where a 
class would be needed.


One difference is, class requires the 'override' keyword in the 
subclasses. I really don't know any technical difference.


Ali



Re: Question on shapes

2022-05-17 Thread forkit via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 04:37:58 UTC, Ali Çehreli wrote:




In you OOP example, I am curious why you chose Shape to be an 
interface, rather than a base class.




Re: Question on shapes

2022-05-17 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 05:08:30 UTC, matheus wrote:



In D there would be a better way to do such thing?



Nothing really specific to D, but for one or two properties, you 
might just add them as function parameters with default values:


```d
void draw(float scale = 1.0f);
```

If you have a number of them (scale, color, blend state, etc.), 
then you might add them as members of the `Shape` class. You 
could then expand on that with a single draw function in the 
`Shape` class that handles the actual drawing, and the subclasses 
would then call that internally after, e.g., setting up any 
vertex buffers or whatever specific to the shapes.


```d
class Shape {
   private:
  float scale;
  RGBA color;
  DrawBuffer buffer; // some API-specific vertex buffer or 
whatever


   protected:
  void drawImpl() { // get the shape on screen }

   public:
  abstract void draw();
}

class Circle {
   override void draw() {
  // set up buffer
  ...
  drawImpl();
}
```

Or you could have a `DrawProperties` struct independent of the 
`Shape` hierarchy that you can fill out and pass to every draw 
call. Or set global properties in the renderer and draw objects 
that have the same properties all at once.


There are several ways to go about it.


Re: Question on shapes

2022-05-17 Thread bauss via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 00:10:55 UTC, Alain De Vos wrote:
Let's say a shape is ,a circle with a radius ,or a square with 
a rectangular size.
I want to pass shapes to functions, eg to draw them on the 
screen,

draw(myshape) or myshape.draw();
But how do i implement best shapes ?


In addition to all the answers, just remember that if you want to 
make a square class then it should inherit from the shape class 
and not the rectangle class.


It might seem like the obvious rule is for square to inherit 
rectangle, since a square is a rectangle, but it's only true on 
the surface, not in functionality.


An example is below:

```d
void changeRectangle(Rectangle rectangle, int amount)
{
  rectangle.length = rectangle.length + amount;
}

...

// While this works, then it's functional wrong as you must 
change both the length/height of a square, since they cannot 
differ.

changeRectangle(new Square(100, 100), 50);
```

You might think that it's easy to just not call changeRectangle 
with a square, but what if you store the rectangles in a list, 
map, get it from an external data source etc. then it starts 
being more and more complex and for no reason at all!


I know your post really isn't about such things, but I think it's 
a good thing to learn already.


Re: Question on shapes

2022-05-17 Thread Ali Çehreli via Digitalmars-d-learn

On 5/16/22 22:08, matheus wrote:

> interface Shape {
>void draw();
>void draw(float scale);
> }

Interfaces can have 'final' functions:

interface Shape {
  void draw(float scale);

  final void draw() {
draw(1);
  }
}

Obviously, for that to work, now Circle.draw() etc. required to respond 
to a 'scale' parameter.


> In D there would be a better way to do such thing?

Reminding that class hierarchies can be deeper as well:

interface A {}
class B : A {  void foo() {} }
class C : B { override void foo() {} }

Ali



Re: Question on shapes

2022-05-16 Thread matheus via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 04:37:58 UTC, Ali Çehreli wrote:

...
2) If you want to have a shape hierarchy, then you can start by 
defining its interface and implement that interface by concrete 
shape types. Drawing is ordinarily handled by member functions:

...


Hi Ali, I'm not the author but I have a question, in your second 
example, let's say that sometimes it would be required to "draw" 
with some scale factor, so (As a newbie) I would do something 
like this:


interface Shape {
  void draw();
  void draw(float scale);
}

Then in Circle class:

  void draw(float scale) {
writeln("This circle's radius is ", radius*scale);
  }
  void draw(){ draw(1); }

Then in Rectangular class:

  void draw(float scale) {
writefln!"This rectangle's dimensions are 
%sx%s."(width*scale,height*scale);

  }
  void draw(){ draw(1); }


So calling shape.draw() would draw with the original scale, 
otherwise you could call as shape.draw(some_scale);


The problem is these are just 2 shapes and it could be much more, 
so it would required to repeat all this.


In D there would be a better way to do such thing?

Thanks,

Matheus.


Re: Question on shapes

2022-05-16 Thread Ali Çehreli via Digitalmars-d-learn

On 5/16/22 17:10, Alain De Vos wrote:
Let's say a shape is ,a circle with a radius ,or a square with a 
rectangular size.

I want to pass shapes to functions, eg to draw them on the screen,
draw(myshape) or myshape.draw();
But how do i implement best shapes ?


There are many ways of achieving this but I think you are looking for 
the classic object-oriented (OOP) shape hierarchy. (Option 2 below.)


1) This option does not use OOP. It uses function overloading:

import std.stdio;

struct Circle {
  float radius;
}

void draw(Circle circle) {
  writeln("This circle's radius is ", circle.radius);
}

struct Rectangle {
  float width;
  float height;
}

void draw(Rectangle rectangle) {
  writefln!"This rectangle's dimensions are %sx%s."(rectangle.width, 
rectangle.height);

}

void main() {
  draw(Circle(1.5));
  draw(Rectangle(2.5, 3.5));
}

That's very simple but it does not allow putting different types of 
shapes e.g. in the same array.



2) If you want to have a shape hierarchy, then you can start by defining 
its interface and implement that interface by concrete shape types. 
Drawing is ordinarily handled by member functions:


import std.stdio;

// This defines what we can do with a Shape:
interface Shape {
  void draw();
}

// This type is now a 'class' that implements Shape.
class Circle : Shape {
  float radius;

  // Classes require constructors; so here is one:
  this (float radius) {
this.radius = radius;
  }

  // No parameter needed. This function always executes on
  // 'this' object.
  void draw() {
writeln("This circle's radius is ", radius);
  }
}

// Similarly, a class
class Rectangle : Shape {
  float width;
  float height;

  this(float width, float height) {
this.width = width;
this.height = height;
  }

  void draw() {
writefln!"This rectangle's dimensions are %sx%s."(width, height);
  }
}

// Here is the promise of polymorphism: This function takes
// a Shape but the special drawing of each shape type is
// handled automatically.
void use(Shape shape) {
  shape.draw();
}

void main() {
  // Class hierarchies allow putting different types into
  // the same array:
  Shape[] shapes;

  // Let's populate with alternating circles and rectangles
  foreach (i; 1 .. 10) {
if  (i % 2) {
  shapes ~= new Circle(i);

} else {
  shapes ~= new Rectangle(i, i * 2);
}
  }

  // And finally let's use them
  foreach (shape; shapes) {
use(shape);
  }
}

Ali


Question on shapes

2022-05-16 Thread Alain De Vos via Digitalmars-d-learn
Let's say a shape is ,a circle with a radius ,or a square with a 
rectangular size.

I want to pass shapes to functions, eg to draw them on the screen,
draw(myshape) or myshape.draw();
But how do i implement best shapes ?


Re: Beginner memory question.

2022-04-19 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Apr 19, 2022 at 05:01:15PM +, Era Scarecrow via Digitalmars-d-learn 
wrote:
[...]
> In linux using zram i've allocated and made a compressed drive of 8Gb
> which took only 200k of space [...] All unallocated pages are assumed
> null/zero filled, and if you zeroize a block it will unallocate the
> space. Makes extracting memory bomb archives (*Terabytes of zeroized
> files to fill space*) becomes rather safe in that environment.
[...]

Don't be too confident about the safety of extracting memory bomb
archives. All the attacker has to do is to make an archive of gigantic
files containing 1's instead... The repeated bytes will make it compress
with very high ratio (likely the same ratio as zeroes), but when
extracting, the kernel will not be able to optimize away pages filled
with 1's.


T

-- 
Skill without imagination is craftsmanship and gives us many useful objects 
such as wickerwork picnic baskets.  Imagination without skill gives us modern 
art. -- Tom Stoppard


Re: Beginner memory question.

2022-04-19 Thread Era Scarecrow via Digitalmars-d-learn

On Saturday, 16 April 2022 at 20:48:15 UTC, Adam Ruppe wrote:

On Saturday, 16 April 2022 at 20:41:25 UTC, WhatMeWorry wrote:

Is virtual memory entering into the equation?


Probably. Memory allocated doesn't physically exist until 
written to a lot of the time.


This might be very much an OS implementation issue.

 In linux using zram i've allocated and made a compressed drive 
of 8Gb which took only 200k of space (*the data i needed to 
extract compresses very well and only be temporarily used*) as 
such saying i have said space even though i have only 4Gb of ram 
didn't seem to matter. All unallocated pages are assumed 
null/zero filled, and if you zeroize a block it will unallocate 
the space. Makes extracting memory bomb archives (*Terabytes of 
zeroized files to fill space*) becomes rather safe in that 
environment.


 I would think if it's a small space (*say 32Mb or under, or some 
percentage like less than 1% of available memory*) it would 
allocate the memory and immediately return it. If it's larger it 
may say it allocated a range of memory (*as long as RAM+VM could 
hold it*) and allocate as needed. The CPU issues page faults when 
you try to access unallocated memory or memory that's not in at 
the time and passes it to a handler; It would then allocate the 
page(*s*) and then resume as though it was always allocated 
(*alternatively suspend until it has free ram, or save the 
program to disk for later resuming if there's no open 
ports/writable-files, or just crash the program with a segment 
fault*). It will make some things faster, and other things slower.


 If it tries to allocate all memory all at once, it may fill up 
RAM, then swap pages out, then fill RAM up again until the said 
space is successful. Which could be wasteful and slow. Or maybe 
it will allocate/reserve necessary Swap space and then allocate 
as much memory as it can before returning to the process.


 When you run out of ram and there's tons of swapping, a fast 
computer can turn into a brick for several minutes for the 
simplest of commands, at which changing swap settings can improve 
things.





Re: Beginner memory question.

2022-04-19 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Apr 19, 2022 at 12:54:06PM +, bauss via Digitalmars-d-learn wrote:
> On Saturday, 16 April 2022 at 20:48:15 UTC, Adam Ruppe wrote:
> > On Saturday, 16 April 2022 at 20:41:25 UTC, WhatMeWorry wrote:
> > > Is virtual memory entering into the equation?
> > 
> > Probably. Memory allocated doesn't physically exist until written to
> > a lot of the time.
> 
> You can also exceed your RAM in a lot of cases, as the OS will just
> start using your disk for RAM instead, so just because you have 8 GB
> of ram doesn't always mean you can only use 8 GM of RAM (in theory of
> course.)

In practice, having your program use more RAM than you have causes the
OS to start thrashing on I/O as it scrambles to load/unload pages from
the cache as your code accesses that (virtual) memory. Other programs
get swapped out, everything slows down to a crawl, and your harddrive
lifetime decreases by a couple of months (or maybe a year or two).

So yeah, in theory definitely possible (and in fact workable as long as
each individual program's entire working set can fit in RAM at the same
time -- the OS can then swap out the other programs while that one
program runs), but not something you want to push. Performance will slow
down to an unusable crawl, and you may need a hard reboot if you don't
want to spend the rest of the day waiting for the I/O thrashing to catch
up with itself.

Not worth it.


T

-- 
Chance favours the prepared mind. -- Louis Pasteur


Re: Beginner memory question.

2022-04-19 Thread bauss via Digitalmars-d-learn

On Saturday, 16 April 2022 at 20:48:15 UTC, Adam Ruppe wrote:

On Saturday, 16 April 2022 at 20:41:25 UTC, WhatMeWorry wrote:

Is virtual memory entering into the equation?


Probably. Memory allocated doesn't physically exist until 
written to a lot of the time.


You can also exceed your RAM in a lot of cases, as the OS will 
just start using your disk for RAM instead, so just because you 
have 8 GB of ram doesn't always mean you can only use 8 GM of RAM 
(in theory of course.)


Re: Beginner memory question.

2022-04-16 Thread Adam Ruppe via Digitalmars-d-learn

On Saturday, 16 April 2022 at 20:41:25 UTC, WhatMeWorry wrote:

Is virtual memory entering into the equation?


Probably. Memory allocated doesn't physically exist until written 
to a lot of the time.


Beginner memory question.

2022-04-16 Thread WhatMeWorry via Digitalmars-d-learn
I'm playing around with dynamic arrays and I wrote the tiny 
program (at bottom). I get the following output:


PS C:\D\sandbox> dmd -m64 maxMem.d
PS C:\D\sandbox> .\maxMem.exe
Reserving 1,610,613,245 elements
reserve() returned a size of: 1,610,613,245
The capacity() of big is 1,610,613,245
ulong.sizeof (num bytes) = 8
Total bytes allocated = 12,884,905,960
Total megabytes allocated = 12,288
Total gigabytes allocated = 12


The discrepancy occurs because my Windows 10 computer only has 
8.0 GB of memory (and that is not even taking the OS into 
consideration).  Are my mega and giga sizes wrong?  Is virtual 
memory entering into the equation?



import std.stdio, std.array, std.algorithm;
import std.format;
import core.exception;

void main()
{
ulong[] big;

// reserve returns the new capacity of the array
ulong e = 1_610_613_245;   // 1_610_613_246 returns out of 
memory error

writeln("Reserving ", format("%,3d", e) ," elements");
auto u = big.reserve(e);

writeln("reserve() returned a size of: ", format("%,3d", u) );

writeln("The capacity() of big is ", format("%,3d", 
big.capacity));	

writeln("ulong.sizeof (num bytes) = ", ulong.sizeof);
writeln("Total bytes allocated = ", format("%,3d", e * 
ulong.sizeof));


immutable ulong megabyte = 1_048_576;// (1024 x 1024)
immutable ulong gigabyte = 1024 * 1024 * 1024;

writeln("Total megabytes allocated = ", format("%,3d", (e * 
ulong.sizeof)/megabyte));
writeln("Total gigabytes allocated = ", format("%,3d", (e * 
ulong.sizeof)/gigabyte));

 }


Re: Basic question about size_t and ulong

2022-03-22 Thread Era Scarecrow via Digitalmars-d-learn

On Wednesday, 23 March 2022 at 00:51:42 UTC, Era Scarecrow wrote:

On Tuesday, 22 March 2022 at 21:23:43 UTC, H. S. Teoh wrote:

We already have this:

import std.conv : to;
int x;
long y;
y = x.to!long;  // equivalent to straight assignment / cast
x = y.to!int;   // throws if out of range for int


 This particular usage can be useful, just not in the 
*automatic* sense i was meaning.


 Forgot to add this; for the more automatic mode maybe add a new 
tag say @autodowncast, which may add the .to!passingtype leaving 
said checks without needing to throw casts in a dozen places.


 Though i doubt Walter or Andrei would go for it.


Re: Basic question about size_t and ulong

2022-03-22 Thread Era Scarecrow via Digitalmars-d-learn

On Tuesday, 22 March 2022 at 21:23:43 UTC, H. S. Teoh wrote:

On Tue, Mar 22, 2022 at 09:11 PM, Era Scarecrow wrote:

[...]
I'd almost wish D had a more lenient mode and would do 
automatic down-casting, then complain if it *would* have 
failed to downcast data at runtime.

[...]


We already have this:

import std.conv : to;
int x;
long y;
y = x.to!long;  // equivalent to straight assignment / cast
x = y.to!int;   // throws if out of range for int


 At which point I might as well just do cast(int) on everything 
regardless **BECAUSE** the point of it is **NOT** having to add a 
bunch of conversions or extra bits to it.


 This particular usage can be useful, just not in the *automatic* 
sense i was meaning.


Re: Basic question about size_t and ulong

2022-03-22 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Mar 22, 2022 at 09:11:00PM +, Era Scarecrow via Digitalmars-d-learn 
wrote:
[...]
> I'd almost wish D had a more lenient mode and would do automatic
> down-casting, then complain if it *would* have failed to downcast data
> at runtime.
[...]

We already have this:

import std.conv : to;
int x;
long y;
y = x.to!long;  // equivalent to straight assignment / cast
x = y.to!int;   // throws if out of range for int


T

-- 
Gone Chopin. Bach in a minuet.
I see that you JS got Bach.


Re: Basic question about size_t and ulong

2022-03-22 Thread Era Scarecrow via Digitalmars-d-learn

On Tuesday, 22 March 2022 at 18:47:19 UTC, Ali Çehreli wrote:

On 3/22/22 11:28, Era Scarecrow wrote:
>   So when should you use size_t?

I use size_t for anything that is related to count, index, etc. 
However, this is a contested topic because size_t is unsigned.


 I don't see a problem with that. It's not like you can access 
-300 address space or index (*although making your own index 
function technically you could*). I'm actually surprised signed 
is the default rather than unsigned. Were negative numbers really 
that important in 16bit MS-DOS that C had to have signed as the 
default?


 This question is probably going off topic but still be 
interesting to know if there's an answer.



> Is it better to use int, long, size_t?

D uses size_t for automatic indexes during foreach, and as I 
said, it makes sense to me.


Otherwise, I think the go-to type should be int for small 
values. long, if we know it won't fit in an int.


 Mhmm. More or less this is what i would think. I'm just getting 
sick of either numbers i return that i have to feed into indexes 
and it complains it's too big, or putting what is going to be a 
smaller number in an array because the array type is too small. 
Casting or using masks may resolve the issue, but it may crop up 
again when i make a change or try to compile on a different 
architecture.


 My usual writing at this time is doing my work on a 64bit 
laptop, but sometimes i go and run the 32bit dmd version in 
windows on a different computer and checking for differences 
between ldc/gdc and dmd for if the code complains. I see more and 
more why different versions of compilers/OSes is a pain in the 
ass.


 I'd almost wish D had a more lenient mode and would do automatic 
down-casting, then complain if it *would* have failed to downcast 
data at runtime.


> Or is it better to try to use the smallest type you need that 
> will fulfill the function's needs and just add to handle 
> issues due to downcasting?


That may be annoying, misleading, or error-prone because 
smaller types are converted at least to int in expressions 
anyway:


 Yeah, and i remember reading about optimization in GCC where 
doing smaller types can actually be slower, much like in some 
architectures having offsets in memory address results in a speed 
penalty for non-aligned data.


But yeah, if your function works on a byte, sure, it should 
take a byte.


Expect wild disagreements on this whole topic. :)


Though internally it may be an int...



Re: Basic question about size_t and ulong

2022-03-22 Thread Ali Çehreli via Digitalmars-d-learn

On 3/22/22 11:28, Era Scarecrow wrote:

>   So when should you use size_t?

I use size_t for anything that is related to count, index, etc. However, 
this is a contested topic because size_t is unsigned. As soon as you use 
it in an expression, the whole expression becomes unsigned as well. 
(Related: Usual Arithmetic Conversions at the link below.)


For that reason, at least during an "ask us anything" session at a C++ 
conference, where Andrei was among the panel, Herb Sutter and others 
agreed that it was a mistake to choose unsigned for size_t.


So far, I didn't have much trouble from that decision. I am always 
careful when subtracting two size_ts.


> Is it better to use int, long, size_t?

D uses size_t for automatic indexes during foreach, and as I said, it 
makes sense to me.


Otherwise, I think the go-to type should be int for small values. long, 
if we know it won't fit in an int.


> Or is it better to try to use the smallest type you need that will
> fulfill the function's needs and just add to handle issues due to
> downcasting?

That may be annoying, misleading, or error-prone because smaller types 
are converted at least to int in expressions anyway:


  https://dlang.org/spec/type.html#integer-promotions

(Every D programmer should know the whole section 6.4 there.)

But yeah, if your function works on a byte, sure, it should take a byte.

Expect wild disagreements on this whole topic. :)

Ali



Re: Basic question about size_t and ulong

2022-03-22 Thread Era Scarecrow via Digitalmars-d-learn

On Friday, 18 March 2022 at 23:01:05 UTC, Ali Çehreli wrote:
P.S. On a related note, I used to make the mistake of using 
size_t for file offsets as well. That is a mistake because even 
on a 32-bit system (or build), file sizes can be larger than 
uint.max. So, the correct type is long for seek() so that we 
can seek() to an earlier place and ulong for tell().


 Perhaps we should back up and ask a different question. I've 
been working on adaptation of Reed Solomon Codes, and i keep 
getting thrown with casting errors, to the point where i just 
want to make everything size_t to make the errors go away.


 So when should you use size_t? Is it better to use int, long, 
size_t? Or is it better to try to use the smallest type you need 
that will fulfill the function's needs and just add to handle 
issues due to downcasting?





Re: Basic question about size_t and ulong

2022-03-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/18/22 7:01 PM, Ali Çehreli wrote:

On 3/18/22 14:54, WhatMeWorry wrote:
 > size_t huge = uint.max;  // compiles

That means size_t is uint on that build.


Not that Ali is wrong in the full sense, but this line alone will 
compile on both 64 and 32-bit systems, so it is not informative. 
However, the fact that assigning it to `ulong.max` doesn't work coupled 
with this means that it's 32-bit.


You can use code like this to tell you what your platform bits are:

```d
pragma(msg, cast(int)(size_t.sizeof * 8), " bit");
```

-Steve


Re: Basic question about size_t and ulong

2022-03-18 Thread Ali Çehreli via Digitalmars-d-learn

On 3/18/22 14:54, WhatMeWorry wrote:

> size_t is an alias to one of the unsigned integral basic types, and
> represents a type that is large enough to represent an offset into all
> addressable memory.

In practice, that general description means "size_t is either ulong or 
uint" depending on your platform (or build e.g. -m32 as Adam said).


> size_t huge = uint.max;  // compiles

That means size_t is uint on that build.

Ali

P.S. On a related note, I used to make the mistake of using size_t for 
file offsets as well. That is a mistake because even on a 32-bit system 
(or build), file sizes can be larger than uint.max. So, the correct type 
is long for seek() so that we can seek() to an earlier place and ulong 
for tell().




Re: Basic question about size_t and ulong

2022-03-18 Thread Adam Ruppe via Digitalmars-d-learn

On Friday, 18 March 2022 at 21:54:55 UTC, WhatMeWorry wrote:

Isn't ulong an integer? And isn't memory addresses 64 bits long?


Only if you are doing a 64 bit build. Try using -m64


Basic question about size_t and ulong

2022-03-18 Thread WhatMeWorry via Digitalmars-d-learn

Quoting the D documentation:

size_t is an alias to one of the unsigned integral basic types, 
and represents a type that is large enough to represent an offset 
into all addressable memory.  And I have a line of code:


size_t huge = ulong.max;

dmd GC.d
GC.d(29): Error: cannot implicitly convert expression 
`18446744073709551615LU` of type 'ulong` to `uint



Isn't ulong an integer? And isn't memory addresses 64 bits long?

size_t huge = uint.max;  // compiles

works but now I'm just curious.  I was just seeing what is the 
largest dynamic array I could create.




Re: Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 27, 2022 at 05:42:09PM +, WhatMeWorry via Digitalmars-d-learn 
wrote:
> While studying Ali's book at chapter "Constructor and Other Special
> Functions" and the below code snippet:
[...]
> // Original
> //this(int i) const { writeln("a const object"); }
> //this(int i) immutable { writeln("an immutable object"); }
> //this(int i) shared { writeln("a shared object"); }
> 
> const this(int i) { writeln("a const object"); }
> immutable this(int i) { writeln("an immutable object"); }
> shared this(int i) { writeln("a shared object"); }
[...]
> Assuming I can speak in correct programmer-ese: I was wondering why
> the qualifiers were placed after the function parameter list (int i).
> Just for fun, I moved to type qualifiers before the function
> definitions "this" (like a return type?) and the output was  exactly
> identical.  So I guess my question is, is this just a matter of
> esthetics or is some more nuanced goal at work here?

In method declarations, modifiers like const/immutable/shared play two
distinct roles:

1) Qualifying the return type of the method;
2) Qualifying the implicit `this` parameter of the method.

Historically, D has been rather lax about where qualifiers in the sense
of (2) can go, so that's why:

const this()

is the same as

this() const

They both mean that the implicit `this` parameter (not to be confused
with `this` as the name of the ctor) is const.

Personally, though, I prefer the 2nd form, because the first form could
potentially be ambiguous in non-ctor member functions:

struct S {
const int method();
}

Does the const apply to `int` or to the implicit `this` parameter? It's
not obvious. Better to write it this way:

int method() const; // const applied to `this`
const(int) method();// const applied to return type

N.B. the parentheses in `const(int)` -- while D is lax in allowing you
to write `const int`, that leads to the ambiguous situation above. My
personal recommendation is to always parenthesize qualified types so
that they are never ambiguous.


T

-- 
Mediocrity has been pushed to extremes.


Re: Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/27/22 12:42 PM, WhatMeWorry wrote:

Assuming I can speak in correct programmer-ese: I was wondering why the 
qualifiers were placed after the function parameter list (int i).  Just 
for fun, I moved to type qualifiers before the function definitions 
"this" (like a return type?) and the output was  exactly identical.  So 
I guess my question is, is this just a matter of esthetics or is some 
more nuanced goal at work here?


For constructors, being on the front is not misleading. But for a member 
function that returns a value, take a look:


```d
struct S
{
   int * x;
   const int *foo() { return x; }
}
```

What do you think happens here?

The answer, is that this is a compiler error. The error is that the 
`const` applies to the `this` parameter and *not* the return value. So 
you are accepting a `const S`, and trying to return its member `x` as a 
plain `int *`.


This is why we always recommend putting the `this` modifiers at the end 
of the function to make it visually clear that they don't apply to the 
return value.


-Steve


Re: Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread Dennis via Digitalmars-d-learn

On Thursday, 27 January 2022 at 17:42:09 UTC, WhatMeWorry wrote:
So I guess my question is, is this just a matter of esthetics 
or is some more nuanced goal at work here?


It doesn't matter much for constructors, but in general, the 
problem with placing qualifiers in front is that it looks 
confusing:

```D
struct S
{
immutable int[] f()
{
return [];
}
}
```

This reads as if it returns an `immutable(int[])`, but it 
doesn't, the `immutable` means that it can only be called on 
`immutable` instances of `S`.





Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread WhatMeWorry via Digitalmars-d-learn
While studying Ali's book at chapter "Constructor and Other 
Special Functions" and the below code snippet:



import std.stdio;

struct S {
this(int i) { writeln("an object"); }

// Original
//this(int i) const { writeln("a const object"); }
//this(int i) immutable { writeln("an immutable object"); 
}

//this(int i) shared { writeln("a shared object"); }

const this(int i) { writeln("a const object"); }
immutable this(int i) { writeln("an immutable object"); }
shared this(int i) { writeln("a shared object"); }
}

void main() {
auto m = S(1);
auto c = const(S)(2);
auto i = immutable(S)(3);
auto s = shared(S)(4);
}

Assuming I can speak in correct programmer-ese: I was wondering 
why the qualifiers were placed after the function parameter list 
(int i).  Just for fun, I moved to type qualifiers before the 
function definitions "this" (like a return type?) and the output 
was  exactly identical.  So I guess my question is, is this just 
a matter of esthetics or is some more nuanced goal at work here?






Re: Linkage question

2022-01-24 Thread duser via Digitalmars-d-learn

On Monday, 24 January 2022 at 19:41:30 UTC, frame wrote:
On Monday, 24 January 2022 at 18:30:02 UTC, Stanislav Blinov 
wrote:


The difference is in how arguments are being passed, which you 
seem to have discovered already :)



Would like to know where the linkage format is defined, thx.


It should be here: https://dlang.org/spec/abi.html although 
IIRC it might not be 100% up to date.


Ah, yes. Thanks. Maybe I should read it more carefully =)

It claims that the D calling convention matches C. But it seems 
that the arguments are pushed in order whereas C does it in 
reverse order and the -218697648 value is indeed my 3rd string 
pointer.


that's a bug with dmd or the spec, arguments are currently passed 
in reverse order compared to C on 64-bit even though they should 
be the same


see:
https://issues.dlang.org/show_bug.cgi?id=20204
https://github.com/dlang/dmd/pull/13287
https://github.com/dlang/dlang.org/pull/3120


Re: Linkage question

2022-01-24 Thread Paul Backus via Digitalmars-d-learn

On Monday, 24 January 2022 at 19:41:30 UTC, frame wrote:
It claims that the D calling convention matches C. But it seems 
that the arguments are pushed in order whereas C does it in 
reverse order and the -218697648 value is indeed my 3rd string 
pointer.


Windows has two calling conventions for C functions, `cdecl` and 
`stdcall`. In D, `cdecl` is called `extern (C)` and `stdcall` is 
called `extern (Windows)`. Windows API functions use the 
`stdcall` convention [1], so you need to use `extern (Windows)` 
when calling them from D.


[1] https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170


Re: Linkage question

2022-01-24 Thread frame via Digitalmars-d-learn
On Monday, 24 January 2022 at 18:30:02 UTC, Stanislav Blinov 
wrote:


The difference is in how arguments are being passed, which you 
seem to have discovered already :)



Would like to know where the linkage format is defined, thx.


It should be here: https://dlang.org/spec/abi.html although 
IIRC it might not be 100% up to date.


Ah, yes. Thanks. Maybe I should read it more carefully =)

It claims that the D calling convention matches C. But it seems 
that the arguments are pushed in order whereas C does it in 
reverse order and the -218697648 value is indeed my 3rd string 
pointer.





Re: Linkage question

2022-01-24 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 24 January 2022 at 17:23:01 UTC, frame wrote:

I understand that the linkage must match but besides the name 
mangling, what's happen here? What is the difference if I 
remove the `extern (C)` part from the T alias?


The difference is in how arguments are being passed, which you 
seem to have discovered already :)



Would like to know where the linkage format is defined, thx.


It should be here: https://dlang.org/spec/abi.html although IIRC 
it might not be 100% up to date.


Linkage question

2022-01-24 Thread frame via Digitalmars-d-learn
If I declare a function as extern(C) inside a DLL, I have also to 
cast the function pointer as extern(C) or it fails calling, eg.


```d
// --- my.dll
export extern (C) void log(int mode, string a, string b, string 
c) {

  /* stuff */
}

// --- main.d
alias T = extern (C) void function(int, string, string, string);
auto fnPtr = cast(T)GetProcAddress(/* stuff */);
```

I understand that the linkage must match but besides the name 
mangling, what's happen here? What is the difference if I remove 
the `extern (C)` part from the T alias?


Doing that supplies 2nd and 3rd paramter as fine pointers but the 
1st argument comes wrong (eg. 10 becomes -218697648) and the last 
argument is garbage too, so the D-linkage format is something 
different.


Would like to know where the linkage format is defined, thx.


Re: map question

2022-01-23 Thread Stanislav Blinov via Digitalmars-d-learn
On Sunday, 23 January 2022 at 09:38:57 UTC, Siarhei Siamashka 
wrote:
On Sunday, 23 January 2022 at 09:08:46 UTC, Stanislav Blinov 
wrote:
Using `iota` here incurs additional computation and argument 
copies that are actually never used, i.e. wasted work. So I'd 
say go with `generate`, as that seems the intent.


Isn't this normally a compiler's job to eliminate all unused 
computations and copies?


It is the programmer's job long before it is the compiler's. It 
can do wonders on your "minimal" code but it's not its job to 
read your mind.



```D
auto foobar1(size_t n)
{
return n.iota.map!(_ => 123).array;
}

auto foobar2(size_t n)
{
return generate!(() => 123).take(n).array;
}
```

LDC with "-O -release" command line options generates pretty 
much identical code for foobar1 and foobar2 (I'm only showing 
the main loop, but the rest is also the same):

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar1FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar1FNaNbNfmZAi+0x20>

```

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar2FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar2FNaNbNfmZAi+0x20>

```

Do you have a better example to demonstrate `generate`'s 
superiority?


Try actual work instead of returning a literal :) Like e.g. 
calling dice(50, 50).


One thing to note though - `generate` will always eagerly call 
its function at least once. Which of course should also be 
considered in choosing the desired implementation. I.e. if your 
`n` comes from user and is allowed to be 0, then `generate` 
becomes an inferior choice.


Re: map question

2022-01-23 Thread Siarhei Siamashka via Digitalmars-d-learn
On Sunday, 23 January 2022 at 09:08:46 UTC, Stanislav Blinov 
wrote:
Using `iota` here incurs additional computation and argument 
copies that are actually never used, i.e. wasted work. So I'd 
say go with `generate`, as that seems the intent.


Isn't this normally a compiler's job to eliminate all unused 
computations and copies?


```D
auto foobar1(size_t n)
{
return n.iota.map!(_ => 123).array;
}

auto foobar2(size_t n)
{
return generate!(() => 123).take(n).array;
}
```

LDC with "-O -release" command line options generates pretty much 
identical code for foobar1 and foobar2 (I'm only showing the main 
loop, but the rest is also the same):

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar1FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar1FNaNbNfmZAi+0x20>

```

```
  20:   48 39 c8cmp%rcx,%rax
  23:   74 18   je 3d 
<_D2zz7foobar2FNaNbNfmZAi+0x3d>

  25:   c7 04 8a 7b 00 00 00movl   $0x7b,(%rdx,%rcx,4)
  2c:   48 83 c1 01 add$0x1,%rcx
  30:   48 39 cbcmp%rcx,%rbx
  33:   75 eb   jne20 
<_D2zz7foobar2FNaNbNfmZAi+0x20>

```

Do you have a better example to demonstrate `generate`'s 
superiority?


Re: map question

2022-01-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 22 January 2022 at 23:54:27 UTC, forkit wrote:
On Saturday, 22 January 2022 at 19:55:43 UTC, Stanislav Blinov 
wrote:




thanks for the explanation. That really helped :-)

writeln( generate!(() => dice(0.6, 1.4)).take(howManyTimes) );
[1, 1, 1, 1, 0]

(or after reading Ali's response - getting rid of rnd, and 
using _ )


writeln( howManyTimes.iota.map!(_ => dice(0.6, 1.4)) );
[1, 0, 1, 1, 1]

They produce exactly the same thing, so I guess it comes down 
to personal choice now.


Using `iota` here incurs additional computation and argument 
copies that are actually never used, i.e. wasted work. So I'd say 
go with `generate`, as that seems the intent.


Re: map question

2022-01-22 Thread forkit via Digitalmars-d-learn
On Saturday, 22 January 2022 at 19:55:43 UTC, Stanislav Blinov 
wrote:




thanks for the explanation. That really helped :-)

writeln( generate!(() => dice(0.6, 1.4)).take(howManyTimes) );
[1, 1, 1, 1, 0]

(or after reading Ali's response - getting rid of rnd, and using 
_ )


writeln( howManyTimes.iota.map!(_ => dice(0.6, 1.4)) );
[1, 0, 1, 1, 1]

They produce exactly the same thing, so I guess it comes down to 
personal choice now.




Re: map question

2022-01-22 Thread Ali Çehreli via Digitalmars-d-learn

On 1/22/22 11:32, forkit wrote:
> trying to make sense of the below:

The generate() solution shown by Stanislav Blinov is suitable here.

>  auto rnd = Random(unpredictableSeed);

Somebody else mentioned this before but none of the programs we've seen 
so far seemed to need a special random number generator. So, the default 
one, which is already randomized, would suffice. Just drop the line above.


>  // ok - using 'e =>' makes sense
>  writeln(howManyTimes.iota.map!(e => rnd.dice(0.6,
> 1.4)).format!"%(%s,%)");

When there is a syntactic need for a variable but that variable is not 
used, the idiomatic way of naming that variable is '_':


howManyTimes.iota.map!(_ => dice(0.6, 1.4))

(Note: I did not write rnd.dice.)

Ali



Re: map question

2022-01-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 22 January 2022 at 19:32:07 UTC, forkit wrote:

trying to make sense of the below:


// ---
module test;

import std;

void main()
{
auto rnd = Random(unpredictableSeed);

int howManyTimes = 5;

// ok - using 'e =>' makes sense
writeln(howManyTimes.iota.map!(e => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");


// ok - though using 'howManyTimes =>' doesn't make much 
sense??
writeln(howManyTimes.iota.map!(howManyTimes => 
rnd.dice(0.6, 1.4)).format!"%(%s,%)");


// NOT ok - using '5 =>' - but isn't this effectively the 
same as above line?
//writeln(howManyTimes.iota.map!(5 => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");

}

// ---


No, it's not the same. 'Tis not really a "map question", looks 
more like a question about


https://dlang.org/spec/expression.html#function_literals (see 
#10).


In the second case, you're defining a lambda with single 
parameter named `howManyTimes`, which is not at all related to 
your local variable of the same name. Third case is invalid, as 
you're effectively trying to do this:


auto func(T)(T 5) { return rnd.dice(0.6, 1.4); }

Which, of course, doesn't make any sense, does it? :)

Given your use case (call a function N times), I think `generate` 
would be more appropriate here:


```d
import std.random;
import std.stdio;
import std.range : generate, take;

void main()
{
auto rnd = Random(unpredictableSeed);
int howManyTimes = 5;
generate!(() => rnd.dice(0.6, 
1.4)).take(howManyTimes).writeln;

}

```


map question

2022-01-22 Thread forkit via Digitalmars-d-learn

trying to make sense of the below:


// ---
module test;

import std;

void main()
{
auto rnd = Random(unpredictableSeed);

int howManyTimes = 5;

// ok - using 'e =>' makes sense
writeln(howManyTimes.iota.map!(e => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");


// ok - though using 'howManyTimes =>' doesn't make much 
sense??
writeln(howManyTimes.iota.map!(howManyTimes => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");


// NOT ok - using '5 =>' - but isn't this effectively the 
same as above line?
//writeln(howManyTimes.iota.map!(5 => rnd.dice(0.6, 
1.4)).format!"%(%s,%)");

}

// ---


Re: -debug question

2022-01-20 Thread forkit via Digitalmars-d-learn
On Friday, 21 January 2022 at 02:10:34 UTC, Steven Schveighoffer 
wrote:




thanks Steven (and Ali too).



Re: -debug question

2022-01-20 Thread Ali Çehreli via Digitalmars-d-learn

On 1/20/22 18:07, forkit wrote:
I have a line of code, that I do NOT want executed when -debug is passed 
in.


enforce(!exists(fname), "Oop! That file already exists!");

Is this even possible? (with using -version ..)



The following should do it:

debug {} else {
   foo();
}

Ali


Re: -debug question

2022-01-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/20/22 9:07 PM, forkit wrote:
I have a line of code, that I do NOT want executed when -debug is passed 
in.


enforce(!exists(fname), "Oop! That file already exists!");

Is this even possible? (with using -version ..)



`debug` is like a `version` block.

```d
debug {} else {
  // code that runs when -debug is not present
}
```

-Steve


  1   2   3   4   5   6   7   8   9   10   >