Re: What are (were) the most difficult parts of D?

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

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


dip1000


While loop on global variable optimised away?

2022-05-11 Thread ichneumwn via Digitalmars-d-learn

Hi Forum,

I have a snippet of code as follows:
```
extern(C) extern __gshared uint g_count;

// inside a class member function:
  while(g_count) <= count) {}
```

This is from a first draft of the code without proper thread 
synchronisation. The global variable g_count is updated from a 
bit of C++ code. As soon as I turn the optimiser on, the code 
never gets passed this point, leading me to suspect it gets 
turned into

```
  while(true) {}
```

If modify the code in the following way:

```
  import core.volatile : volatileLoad;

  while(volatileLoad(&g_count) <= count) {}
```

it works again.

My question is, have I hit a compiler bug (ldc 1.28.1, aarch64 
[Raspberry Pi]) or is this part of the language design. I would 
have thought since D use thread-local storage by default, that 
for a __gshared variable it would be understood that it can get 
modified by another thread. Access through atomic function would 
prevent the compiler from optimising this away as well, but if I 
were to use a Mutex inside the loop, there is no way for the 
compiler to tell *what* that Mutex is protecting and it might 
still decide to optimise the test away (assuming that is what is 
happening, did not attempt to look at the assembler code).


Cheers



Re: While loop on global variable optimised away?

2022-05-11 Thread rikki cattermole via Digitalmars-d-learn
Compiler optimizations should not be defined by a programming language 
specification.


This will be on LLVM.


Re: While loop on global variable optimised away?

2022-05-11 Thread Johan via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 09:34:20 UTC, ichneumwn wrote:

Hi Forum,

I have a snippet of code as follows:
```
extern(C) extern __gshared uint g_count;

// inside a class member function:
  while(g_count) <= count) {}
```

This is from a first draft of the code without proper thread 
synchronisation. The global variable g_count is updated from a 
bit of C++ code. As soon as I turn the optimiser on, the code 
never gets passed this point, leading me to suspect it gets 
turned into

```
  while(true) {}
```

If modify the code in the following way:

```
  import core.volatile : volatileLoad;

  while(volatileLoad(&g_count) <= count) {}
```

it works again.

My question is, have I hit a compiler bug (ldc 1.28.1, aarch64 
[Raspberry Pi]) or is this part of the language design. I would 
have thought since D use thread-local storage by default, that 
for a __gshared variable it would be understood that it can get 
modified by another thread.


This is part of the language spec. The language assumes that 
there is a single thread running, and any thread synchronization 
must be done by the user. This is well known from C and C++, from 
which D (implicitly afaik) borrows the memory model.


Example: imagine loading a struct with 2 ulongs from shared 
memory: `auto s = global_struct_variable;`. Loading the data into 
local storage `s` - e.g. CPU registers - would happen in two 
steps, first member1, then member2 (simplified, let's assume it 
spans across a cache boundary, etc..). During that load sequence, 
another thread might write to the struct. If the language must 
have defined behavior in that situation (other thread write), 
then a global mutex lock/unlock must be done before/after _every_ 
read and write of shared data. That'd be a big performance impact 
on multithreading. Instead, single-thread execution is assumed, 
and thus the optimization is valid.


Your solution with `volatileLoad` is correct.

Access through atomic function would prevent the compiler from 
optimising this away as well, but if I were to use a Mutex 
inside the loop, there is no way for the compiler to tell 
*what* that Mutex is protecting and it might still decide to 
optimise the test away (assuming that is what is happening, did 
not attempt to look at the assembler code).


Any function call (inside the loop) for which it cannot be proven 
that it never modifies your memory variable will work. That's why 
I'm pretty sure that mutex lock/unlock will work.



On Wednesday, 11 May 2022 at 09:37:26 UTC, rikki cattermole wrote:
Compiler optimizations should not be defined by a programming 
language specification.


This is not true. Compiler optimizations are valid if and only if 
they can be proven by the programming language specification. A 
compiler optimization can never change valid program behavior. If 
an optimization does change behavior, then either the program is 
invalid per the language spec, or the optimization is bugged (or 
the observed behavior change is outside the language spec, such 
as how long a program takes to execute).



-Johan




Re: While loop on global variable optimised away?

2022-05-11 Thread ichneumwn via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 10:01:18 UTC, Johan wrote:

Any function call (inside the loop) for which it cannot be 
proven that it never modifies your memory variable will work. 
That's why I'm pretty sure that mutex lock/unlock will work.


Thank you, in C I would not have been surprised. It was the 
default thread local storage that made me question it. Your 
remark about the mutex lock/unlock is very helpful, I was 
starting to get worried I would need to keep a very careful watch 
on those __gshareds [well, more than usual :) ]




Re: Trait for "can be instantiated"?

2022-05-11 Thread Basile B. via Digitalmars-d-learn

On Tuesday, 10 May 2022 at 16:10:26 UTC, Ben Jones wrote:

On Tuesday, 10 May 2022 at 16:05:15 UTC, H. S. Teoh wrote:
Using wrapper structs, etc., for this is IMO total overkill. 
Just use an enum for your token types.  Something like this 
would suffice:


That's basically what sumtype is going to do for me, but 
(hopefully) more safely. Also, the token types are "user 
defined,"  my lexer just grabs everything annotated with @Token 
and passes those types/wrapped enums to sumtype.


How about being more explicit in the UDA ?
The idea would be to associate the enum value to a type or not:

```d
import std.traits;
import std.stdio;

struct Token(T);

struct Token(T...)
if (T.length == 0) { }

@Token!(string) enum str_tok;
@Token!(float)  enum float_tok;
@Token!()   enum lparen_tok;

void main()
{
alias toks = getSymbolsByUDA!(mixin(__MODULE__), Token);

static foreach (t; toks)
{{
alias U = getUDAs!(t, Token);
alias A = TemplateArgsOf!(U);
static if (A.length)
pragma(msg, "add a `" ~ A[0].stringof ~ "`for `" ~ 
t.stringof ~ "`");

else
pragma(msg, "no SumType data needed for `" ~ 
t.stringof ~ "`");

}}
}
```


Re: What are (were) the most difficult parts of D?

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

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


I don't know if this will be helpful but here it goes, my user 
case is different since I use D as C on steroids.


My first language was C and I have projects in this language 
which I still maintain and my brain is used to it, but depending 
the project I'll use D instead of C to use features like: GC, AA, 
Strings, Modules and maybe Classes if I feel like it, but I don't 
go to far from these and one reason is sometimes in a rich 
language with lots of features like D It gets hard to stay up to 
date.


Now I know they must be useful to many others, but one thing that 
I don't like are the Attributes part, for me there are so many 
and this is a bit overwhelming (Again to me), for example need to 
think about: "@safe, @trusted, @system" while still prototyping 
may be a cumbersome, and if it's giving me trouble I'll just get 
rid of it. :)


Again I should sit and read the documentation or your book again 
but it's hard to keep up-to-date sometimes with work and so on.


By the way I used to program in C# at work too, but I stopped on 
whatever was the version that runs with .Net 4.6, again this is 
another case of language changing or adding so many features that 
I decided not to go on with it, since it's not required where I 
work (Occasionally I write a few batch programs here and there), 
and I'm current doing more database business at the company these 
days,


Sorry for any English mistakes,

Matheus.


Virtual methods on stack objects

2022-05-11 Thread Marvin Hannott via Digitalmars-d-learn

Hi everybody!

I understand that D's classes solve some particular problems. 
However, they also cause problems because they cannot be copied 
when scoped. So how do I get virtual methods on a copyable stack 
object?


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, May 11, 2022 at 01:37:21PM +, matheus via Digitalmars-d-learn wrote:
> On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
> > What are you stuck at? What was the most difficult features to
> > understand? etc.
> > 
> > To make it more meaningful, what is your experience with other
> > languages?
[...]
> Now I know they must be useful to many others, but one thing that I
> don't like are the Attributes part, for me there are so many and this
> is a bit overwhelming (Again to me), for example need to think about:
> "@safe, @trusted, @system" while still prototyping may be a
> cumbersome, and if it's giving me trouble I'll just get rid of it. :)
[...]

My suggestion is: when prototyping, don't even think about attributes.
Just templatize your functions and let the compiler infer the attributes
for you.

I myself rarely bother with attributes; I only write them when I want to
be 100% sure that a particular piece of code has that attribute.
Otherwise I just templatize it and let the compiler figure it out for
me.  Auto-inference is the way to go; life is too short to be fiddling
with attributes in every single declaration manually.


T

-- 
People walk. Computers run.


Re: Virtual methods on stack objects

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

On 5/11/22 06:57, Marvin Hannott wrote:

> I understand that D's classes solve some particular problems. However,
> they also cause problems because they cannot be copied when scoped. So
> how do I get virtual methods on a copyable stack object?

Problems classes solve don't usually need copying nor need to be on the 
stack. Is that really necessary?


If so, I can think of two solutions:

a) Use a struct but provide "virtual" functions manually (with function 
pointers like one would do in C, all of which potentially collected in a 
per-type function table (a.k.a. vtbl :) )).


b) Use classes but provide a virtual function that you call to copy.

Ali



Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Tejas via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 14:20:07 UTC, H. S. Teoh wrote:
On Wed, May 11, 2022 at 01:37:21PM +, matheus via 
Digitalmars-d-learn wrote:

> [...]

[...]

[...]

[...]

My suggestion is: when prototyping, don't even think about 
attributes. Just templatize your functions and let the compiler 
infer the attributes for you.


I myself rarely bother with attributes; I only write them when 
I want to be 100% sure that a particular piece of code has that 
attribute. Otherwise I just templatize it and let the compiler 
figure it out for me.  Auto-inference is the way to go; life is 
too short to be fiddling with attributes in every single 
declaration manually.



T


That'll be true the day when `@safe` becomes the default... Until 
then, I'll atleast do `@safe:` on top of every module :)


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 15:10:28 UTC, Tejas wrote:
That'll be true the day when `@safe` becomes the default... 
Until then, I'll atleast do `@safe:` on top of every module :)


`@safe:` is actually a bad idea if you're writing templated code, 
because it turns inference of `@system` into a compile-time error:


```d
@safe:

auto map(alias fun, T)(T[] arr)
{
auto result = arr.dup;
foreach (ref e; result) e = fun(e);
return result;
}

int safeDouble(int n) @safe { return 2*n; }
int systemDouble(int n) @system { return 2*n; }

void main() @system
{
int[] a = [1, 2, 3];
// ok
auto b = a.map!safeDouble;
// Error: `@safe` function `map!systemDouble` cannot call 
`@system` function `systemDouble`

auto c = a.map!systemDouble;
}
```

Without `@safe:` at the top, `map!systemDouble` would have been 
inferred as `@system`, and calling it from a `@system` `main` 
function would have been allowed.


Re: Trait for "can be instantiated"?

2022-05-11 Thread Ben Jones via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 12:29:05 UTC, Basile B. wrote:

How about being more explicit in the UDA ?
The idea would be to associate the enum value to a type or not:


I think that could work but would require some major changes to 
my existing code.  Also, I think I'd prefer:


```
@Token{

 enum lparen = '(';
 enum rparen = ')';
 enum if_token;
}
```

to what you suggested as a user of the library.


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, May 11, 2022 at 03:34:12PM +, Paul Backus via Digitalmars-d-learn 
wrote:
> On Wednesday, 11 May 2022 at 15:10:28 UTC, Tejas wrote:
> > That'll be true the day when `@safe` becomes the default... Until
> > then, I'll atleast do `@safe:` on top of every module :)
> 
> `@safe:` is actually a bad idea if you're writing templated code,
> because it turns inference of `@system` into a compile-time error:

Yeah, for templated code, what you want is a @safe unittest that ensures
that the code is @safe when whatever you instantiate it with is @safe:

auto myTemplateFunc(Args...)(Args args)
/* N.B.: no attributes */
{
return ...;
}

@safe unittest {
// This ensures that myTemplateFunc is callable from
// @safe when instantiated with @safe arguments.
auto result = myTemplateFunc(... /* @safe arguments */);
}

This way, it's possible to instantiate myTemplateFunc with @system
arguments (you get a @system instantiation).


T

-- 
Life is unfair. Ask too much from it, and it may decide you don't deserve what 
you have now either.


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread jmh530 via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 09:06:52 UTC, bauss wrote:

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


dip1000


Ha, I just mentioned this on another thread...
https://dlang.org/spec/function.html#ref-return-scope-parameters


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


No singular feature, but the overall cognitive load if you use 
the language sporadic. Which could be most users that don't use 
it for work or have it as their main hobby.


As with all languages, cognitive load increases when things do 
not work as one would intuitively expect or if a feature is 
incomplete in some specific case. D has some of the same issues 
as C++, you either deal with details or you can choose to go more 
minimalistic in your usage.


If you read other people's D code you can easily (IMO) see that 
there is no unified style or usage of features, so it seems like 
people stick to their own understanding of «good code», which can 
make it tiresome to read D code by others (e.g. standard 
library). I guess some good coherent educational material is 
missing, people are finding their own way. There are no obvious 
codebases that highlight «best practice». I suspect 
meta-programming is pushed too much and that this has a negative 
effect on legibility of code bases.


You basically increase the cognitive load further if you choose 
to be slightly different from other languages, and focus on 
special cases. Examples: the proposal for interpolated strings, 
dip1000, certain aspects of D's generics syntax etc.


When you already have high cognitive load you should be very 
careful about not adding more "slightly unusual/unexpected" 
semantics/syntax.



To make it more meaningful, what is your experience with other 
languages?


I believe what makes Python a favoured language by many is that 
you can use it sporadically without relearning. Spending less 
time reading documentation is always a win.


To do things right in C++ you have to look things up all the 
time, this is only ok for people who use it many hours every week.


In general I think the ergonomics would be much better if the 
historical baggage from C/C++ had been pushed aside in favour of 
a more intuitive clean approach. I am not sure if many new users 
have a good understanding of C/C++ anyway.


Of course, this perspective is highly irrelevant as it is clear 
now that the current direction of language evolution is to 
continue to absorb C and not really be provide a clean 
improvement over C, but more like an extension. (More like C++ 
and Objective-C than Rust).


I think it will be difficult to attract young programmers with 
this approach as they are less likely to be comfortable with the 
peculiarities of C.




Re: What are (were) the most difficult parts of D?

2022-05-11 Thread templatedperson via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.




I don't know if this counts as a feature, but reading the 
standard library documentation was especially difficult. There 
are a ton of `auto`s everywhere and function signatures are hard 
to read because of that. I got used to confusing function 
signatures in a week or two, but it made me consider not using D.


To make it more meaningful, what is your experience with other 
languages?




Rust does a better job at this. Generics are strongly-typed with 
`trait`s. In D, we have to type-check `struct`s ourselves by 
adding `if (is(T == SomeType))` etc. after the function 
declaration. In Rust, you can create a `trait` and use that as 
the parameter type in a function.


In D we can have this with `interface`s when we're using 
`class`es but we can't have this for `struct`s. Actually, I'd 
appreciate if we could get `static interface`s or something, so 
that people won't need to type-check manually.


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Guillaume Piolat via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


- How to do deterministic destruction with programs that use 
everything (struct / class / dynamic dispatch / GC / manual / 
etc). This requires to understand what the runtime does, what the 
gc does.

  Interesting nonetheless.

- Some traps. Accidental TLS is a thing, top-level should 
probably not be silently TLS.
  People will loose hours on this completely preventable 
thing.

  What was the idea, optimize code without people knowing?

- `shared static this()` vs `static this()` is another trap.
  Honestly would have preferred `__threadlocal`. It's not 
like being thread-local is something completely normal or without 
consequence for platform support.


- Some features lack an escape hatch, notably `pure`. pure 
leaks into identifiers, like `pureMalloc`. Trying to add `pure` 
fails on a large codebase.


- `@safe`/`@trusted`/`@system` is good but the definition of 
what `@trusted` means has to be remembered from the programmer.
  For example `Mutex.lock()` is `@trusted`, it could have 
been `@system` to let user review their usage of locks. You have 
to wonder "can a lock()/unlock() corrupt memory?". People can use 
that to mean "@reviewed" instead. Because it is up to us, the 
exact meaning will float in the D subcultures. A function which 
has been marked `@trusted` does not receive any review whan 
changed later. It will not mean the same as `@trusted` in another 
codebase.


- Generic code typically has bad names (domain-less) and 
worse usability. It's often not pretty to look at. Mostly 
cultural, since D has powerful templates so they had to be 
everywhere. UFCS chains are not that convincing when you are 
worried about maintenance.
  Phobos take short names for itself, this leads to pretty 
complicated operations having a small screen estate.


- `assert(false)` being different and not removed by 
`-release`. Keyword reuse seems entrenched but honestly a "crash 
here" keyword would be more readable.
  It is really 3 different things: assert, crash, and 
unreachable.



Otherwise D is glorious and get syntax and usability right, which 
puts it ahead of almost every other language.


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


Also, if you intend to use the responses for planning purposes, 
keep in mind that people who read the forums regularly are more 
informed about pitfalls than other users. Forum-dwellers have a 
richer understanding of the landscape and probably view the 
feature set in a different light.





Re: What are (were) the most difficult parts of D?

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

On 5/11/22 12:20, Ola Fosheim Grøstad wrote:
> On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
>> What are you stuck at? What was the most difficult features to
>> understand? etc.
>
> Also, if you intend to use the responses for planning purposes

No. :) I was hoping to get responses like "I come from Python and have 
no idea what templates are", "I come from C and have no idea what 
reference types are." Or exceptions, ranges, etc.


Ali



Re: Virtual methods on stack objects

2022-05-11 Thread Marvin Hannott via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 14:44:59 UTC, Ali Çehreli wrote:

On 5/11/22 06:57, Marvin Hannott wrote:

> I understand that D's classes solve some particular problems.
However,
> they also cause problems because they cannot be copied when
scoped. So
> how do I get virtual methods on a copyable stack object?

Problems classes solve don't usually need copying nor need to 
be on the stack. Is that really necessary?


If so, I can think of two solutions:

a) Use a struct but provide "virtual" functions manually (with 
function pointers like one would do in C, all of which 
potentially collected in a per-type function table (a.k.a. vtbl 
:) )).


b) Use classes but provide a virtual function that you call to 
copy.


Ali


I appreciate the answer, don't much like the "solutions".

It's not so much about copying, but about heap allocations. Tying 
virtual methods to heap allocation is kind of unfortunate. And I 
am not really keen on building a poor man's vtbl.
And for my taste, scoped class objects should have value 
semantics.


Re: Virtual methods on stack objects

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

On 5/11/22 13:06, Marvin Hannott wrote:

> I appreciate the answer, don't much like the "solutions".

Me neither. :)

> It's not so much about copying

Great!

> scoped class objects should have value semantics.

std.typecons.scoped does exactly that:

  https://dlang.org/phobos/std_typecons.html#scoped

import std.stdio;
import std.typecons;

interface Animal {
  string sing();
}

class Cat : Animal {
  this() {
writeln("Hi!");
  }

  ~this() {
writeln("Bye!");
  }

  string sing() {
return "mew";
  }
}

void foo(Animal animal) {
  writeln(animal.sing());
}

void bar() {
  auto cat = scoped!Cat();
  foo(cat);
}

void main() {
  bar();
}

The output:

Hi!
mew
Bye!

Ali



Re: range result in Tuple! and how to convert into assocArray by sort?

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

On 5/9/22 22:12, MichaelBi wrote:
> On Tuesday, 10 May 2022 at 04:21:04 UTC, Ali Çehreli wrote:
>> On 5/9/22 20:38, rikki cattermole wrote:
>>
>> > [...]
>>
>> Yes! :)
>>
>> Assuming the data is indeed validated in some way, the following
>> should be even faster. It validates the data after the fact:
>>
>> [...]
>
> this is cool!

I've been meaning to write about a bug in my code, which would likely 
cause zero issues, and which you've probably already fixed. ;)


 BAD:  auto counts = new ulong[char.max];

GOOD:   auto counts = new ulong[char.max - char.min + 1];
FINE:   auto counts = new ulong[256];

> thanks for your time and i really like your book
> Programming in D :)

Yay! :)

Ali



Re: Virtual methods on stack objects

2022-05-11 Thread Marvin Hannott via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:

On 5/11/22 13:06, Marvin Hannott wrote:

> I appreciate the answer, don't much like the "solutions".

Me neither. :)

> It's not so much about copying

Great!

> scoped class objects should have value semantics.

std.typecons.scoped does exactly that:

  https://dlang.org/phobos/std_typecons.html#scoped

import std.stdio;
import std.typecons;

interface Animal {
  string sing();
}

class Cat : Animal {
  this() {
writeln("Hi!");
  }

  ~this() {
writeln("Bye!");
  }

  string sing() {
return "mew";
  }
}

void foo(Animal animal) {
  writeln(animal.sing());
}

void bar() {
  auto cat = scoped!Cat();
  foo(cat);
}

void main() {
  bar();
}

The output:

Hi!
mew
Bye!

Ali


Yeah, but you can't return `Cat` 😉. And the documentation for 
`scoped` says:
It's illegal to move a class instance even if you are sure there 
are no pointers to it. As such, it is illegal to move a scoped 
object.


That's kinda very limiting.

Anyway, I cooked up another idea based on your first suggestions.
```D
struct S
{
static private interface I
{
int f(int i);
}

static private final class A : I
{
int f(int i) {return i;}
}

static private final class B : I
{
int f(int i) {return i+ 1;}
}

private I i;
private int d;

this(int d)
{
this.d = d;
if(d < 10)
{
i = scoped!A();
}else {
i = scoped!B();
}
}

int f() { return i.f(d);}
}
```
I mean, this is a super dumb example, but it kinda works. And I 
think it could be made a lot less tedious with some mixin magic.


Re: What are (were) the most difficult parts of D?

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

On 5/11/22 11:27, templatedperson wrote:

> I don't know if this counts as a feature, but reading the standard
> library documentation was especially difficult. There are a ton of
> `auto`s everywhere and function signatures are hard to read because of
> that. I got used to confusing function signatures in a week or two, but
> it made me consider not using D.

I agree with readability problems. And although you likely know why 
there are 'auto's everywhere in the standard library, I want to touch on 
that for others who may not know.


Although templates are great, they bring naming problems:

- Some names are overly complex and expose implementation details.

- Some names are unmentionable because the implementation chose to make 
the return type a nested struct.


import std.range;
import std.algorithm;

struct MyStruct {
}

void main() {
  auto arr = [ MyStruct() ];
  auto r = arr.map!(o => o).cycle;
  pragma(msg, typeof(r));
}

The type of the range object 'r' happens to be the scary

  Cycle!(MapResult!(__lambda2, MyStruct[])).

But make a change e.g. by adding .enumerate to the expression

  auto r = arr.map!(o => o).enumerate.cycle;

and now the type is very different (and deceptively simpler!):

  Cycle!(Result)

So, there is nothing else to do in current D but to have 'auto' return 
types.


Ali



Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Christopher Katko via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


Every time I think I understand D, I don't.

Cool useful library functions like sumElement that magically 
don't work on static arrays.


'private' is per module, not per class, making it pretty much 
useless for preventing incorrect access and using .


completely different semantics for a class vs a struct. Is it a 
reference? Is it a value? Look up the entire declaration and have 
the entire Dlang manual open to find out.


As far as I remember, no automatic RAII support, even though it's 
insanely useful. You have to manually write scope(end) stuff 
which means any person forgetting one is now leaking memory.


Writing output in a deconstuctor (for learning) works. But then 
you accidentally combine two strings inside it and the garbage 
collecter crashes without a stack trace.


Documentation. Documentation. Documentation.

I just realized foreach copies by value by default. Maybe. 
Sometimes. When? I don't even know anymore. Because I "thought" I 
had to use foreach(ref) to be able to affect the original data 
structure (because by value means its a copy, right?). Except 
somehow everything has been working just fine, mutating the 
original structure/array from inside foreach and adding 
foreach(ref) makes no changes. Will it be faster? Maybe... who 
knows.


And I really like D! But there's lots of "WTF" moments. There's 
so much I have to Google for a single forum post with dead links 
from 2014 which is only 30% like my use-case that describes my 
error or problem.


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 12 May 2022 at 01:06:02 UTC, Christopher Katko wrote:
completely different semantics for a class vs a struct. Is it a 
reference? Is it a value? Look up the entire declaration and 
have the entire Dlang manual open to find out.


As far as I remember, no automatic RAII support, even though 
it's insanely useful.


class = virtual functions

struct = RAII




Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/11/22 9:06 PM, Christopher Katko wrote:

I just realized foreach copies by value by default. Maybe. Sometimes. 
When? I don't even know anymore. Because I "thought" I had to use 
foreach(ref) to be able to affect the original data structure (because 
by value means its a copy, right?). Except somehow everything has been 
working just fine, mutating the original structure/array from inside 
foreach and adding foreach(ref) makes no changes. Will it be faster? 
Maybe... who knows.


ref can be confusing depending on the type. foreach indeed does 
everything by value unless you specify ref. But some types "act like" a 
ref. Remember, the copy is a *shallow* copy. So a "copy" of an array 
slice, for example, still refers to the original elements.


-Steve


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread zjh via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.




I don't know the progress of `interface to C++`.
I want to use my C++ functions in `d`.

`C++`'s `concept` and `...` is very convenient.




Re: What are (were) the most difficult parts of D?

2022-05-11 Thread zjh via Digitalmars-d-learn

On Thursday, 12 May 2022 at 02:35:50 UTC, zjh wrote:


`C++`'s `concept` and `...` is very convenient.


And C++'s `stackless coroutine`.




Re: Virtual methods on stack objects

2022-05-11 Thread dangbinghoo via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 20:53:21 UTC, Marvin Hannott wrote:

On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:

[...]


Yeah, but you can't return `Cat` 😉. And the documentation for 
`scoped` says:

[...]


That's kinda very limiting.

Anyway, I cooked up another idea based on your first 
suggestions.

```D
struct S
{
static private interface I
{
int f(int i);
}

static private final class A : I
{
int f(int i) {return i;}
}

static private final class B : I
{
int f(int i) {return i+ 1;}
}

private I i;
private int d;

this(int d)
{
this.d = d;
if(d < 10)
{
i = scoped!A();
}else {
i = scoped!B();
}
}

int f() { return i.f(d);}
}
```
I mean, this is a super dumb example, but it kinda works. And I 
think it could be made a lot less tedious with some mixin magic.


add a single `writeln("A.f")` to A.f and `writeln("B.f")` B.f, 
and a simple test


```d
void main()
{
S s1 = S(9);
S s2 = S(12);
s1.f();
s2.f();
}
```

outputs:

```
A.f
Error: program killed by signal 11
(Aka.  segmentation fault !)
```



Re: range result in Tuple! and how to convert into assocArray by sort?

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

On Tuesday, 10 May 2022 at 03:22:04 UTC, MichaelBi wrote:

s is the string, and print result as following:

s.array.sort!("athen how to transfer into 
[['A',231],['C',247],['G',240],['T',209]]? tried map!, but can 
only sortout key or value... tried array(), but result is not 
sorted then...thanks in advance.


Adding tuples to an AA is easy.

Sorting the output of an AA is the tricky part.

// -

module test;
@safe:

import std;

void main()
{
uint[dchar] myAA;
Tuple!(dchar, uint) myTuple;

myTuple[0] = 'C'; myTuple[1] = 247;
myAA[ myTuple[0] ] = myTuple[1];

myTuple[0] = 'G'; myTuple[1] = 240;
myAA[ myTuple[0] ] = myTuple[1];

myTuple[0] = 'A'; myTuple[1] = 231;
myAA[ myTuple[0] ] = myTuple[1];

myTuple[0] = 'T'; myTuple[1] = 209;
myAA[ myTuple[0] ] = myTuple[1];

// NOTE: associative arrays do not preserve the order of the 
keys inserted into the array.

// See: https://dlang.org/spec/hash-map.html

// if we want the output of an AA to be sorted (by key)..
string[] orderedKeyPairSet;

foreach(ref key, ref value; myAA.byPair)
orderedKeyPairSet ~= key.to!string ~ ":" ~ 
value.to!string;


orderedKeyPairSet.sort;

foreach(ref str; orderedKeyPairSet)
writeln(str);

/+
A:231
C:247
G:240
T:209
   +/

}

// 



Re: What are (were) the most difficult parts of D?

2022-05-11 Thread zjh via Digitalmars-d-learn

On Thursday, 12 May 2022 at 02:40:09 UTC, zjh wrote:


And C++'s `stackless coroutine`.


Another one,
I hope the `error message` can be adapted to different languages 
like `chinese/german/russion/turkish` etc.


Re: What are (were) the most difficult parts of D?

2022-05-11 Thread Siemargl via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
What are you stuck at? What was the most difficult features to 
understand? etc.


To make it more meaningful, what is your experience with other 
languages?


Ali


When i take old library from a dub or github and cannot compile 
it with latest compiler because of small and subtle language 
changes.


For example
https://github.com/buggins/dlangide/pull/410/commits/43a82ed2f45143270482aa94c447e577174f0108#diff-375ecd44ef501b93adc6106fe404f55d353e667c21681c1c13a9e2008510ab42L937

I dont know even now, which D's features changes here.