Re: What are (were) the most difficult parts of D?
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?
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?
Compiler optimizations should not be defined by a programming language specification. This will be on LLVM.
Re: While loop on global variable optimised away?
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?
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"?
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?
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
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?
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
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?
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?
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"?
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?
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?
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?
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?
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?
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?
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?
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
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
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?
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
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?
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?
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?
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?
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?
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?
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
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?
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?
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?
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.