Re: Negating a short?
On Wednesday, 6 November 2024 at 16:38:40 UTC, Salih Dincer wrote: In response to Andy and Matheus, I think implementing your own type might be a solution: Oh, am I too hasty? There was already an s in the test environment, so I thought 2 overloads were unnecessary. I don't have a programmer or anything, my brother :) In fact, it would be nice if there was an option to correct the threads we wrote on our forum. At least for a certain period of time. Here is the latest code that works: ```d void main() { Short foo = { 21 }; foo *= -1; foo = foo * -2; assert(foo.s == 42); } struct Short { short s; auto opBinary(string op: "*")(int rhs) { auto result = s * rhs; return Short(cast(short)result); } void opOpAssign(string op: "*")(int rhs) { s *= rhs; } } SDB@79
Re: Negating a short?
On Wednesday, 6 November 2024 at 16:25:40 UTC, Salih Dincer wrote: In response to Andy and Matheus, I think implementing your own type might be a solution: Even in my own type, single overload was enough. So I have to correct my mistake: ```d void main() { Short foo = { -21 }; s *= -1; foo = foo * -2; assert(foo.s == 42); } struct Short { short s; auto opBinary(string op: "*")(int rhs) { auto result = s * rhs; return Short(cast(short)result); } } ``` SDB@79
Re: Negating a short?
On Tuesday, 5 November 2024 at 17:32:00 UTC, Andy Valencia wrote: integral promotion not done for -val ```d I ended up with this, but is negating a short really this problematic, or did I miss something? static if (!__traits(isUnsigned, T)) { if (val < 0) { static if (__traits(getPointerBitmap, T)[0] < int.sizeof) { val = cast(T)(-(cast(int)val)); } else { val = -val; } } } ``` In response to Andy and Matheus, I think implementing your own kind might be a solution: ```d void main() { Short foo = { -21 }; foo = foo * -2; assert(foo.s == 42); } struct Short { short s; auto opBinary(string op: "*")(int rhs) { auto result = s * rhs; return Short(cast(short)result); } void opOpAssign(string op: "*")(int rhs) { s *= rhs; } } ``` SDB@79
Re: NGINX Unit and vibe.d Integration Performance
On Sunday, 3 November 2024 at 00:42:44 UTC, Kyle Ingraham wrote: "You can add an explicit sub configuration to dub.json: ```json "dependencies": { "vibe-d": "~>0.10.1", "eventcore": "~>0.9.34" }, "subConfigurations": { "eventcore": "kqueue" }, ``` Or you could pass --override-config=eventcore/kqueue to the dub invocation to try it out temporarily." I'm glad to hear that. In the world of software, there is actually no problem that cannot be solved; except for the halting problem :) SDB@79
Re: Do not able to install DMD Compiler with curl
On Thursday, 31 October 2024 at 08:18:58 UTC, Jordan Wilson wrote: I've had this before, and `./install.sh update` solved it, except for on Fedora, I couldn't for the life of me figure out how to use the install script to install dmd (ldc and gdc installed just fine). Jordan Thank you suggestions but no works on my operating system (Windows11), Here's can I do with MYSYS2: ``` md@SDB MSYS ~ $ mkdir -p ~/dlang && wget https://dlang.org/install.sh -O ~/dlang/install.sh --2024-10-31 11:49:27-- https://dlang.org/install.sh Loaded CA certificate '/usr/ssl/certs/ca-bundle.crt' Resolving dlang.org (dlang.org)... 162.217.114.56, 2607:fc50:1:ff02::5:0 Connecting to dlang.org (dlang.org)|162.217.114.56|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 38449 (38K) [application/x-sh] Saving to: ‘/home/md/dlang/install.sh’ /home/md/dlang/install.s 100%[==>] 37.55K 68.7KB/sin 0.5s 2024-10-31 11:49:29 (68.7 KB/s) - ‘/home/md/dlang/install.sh’ saved [38449/38449] ``` ``` md@SDB MSYS ~ $ cd dlang md@SDB MSYS ~/dlang $ ls d-keyring.gpg install.sh ``` ``` md@SDB MSYS ~ $ ./install.sh update Downloading https://dlang.org/d-keyring.gpg # 100.0% gpg: Signature made Tue Feb 14 01:52:51 2023 +03 gpg:using RSA key E22EC04C82780970381402F4A7D4D42F8EC6A355 gpg: Can't check signature: No public key Invalid signature https://dlang.org/d-keyring.gpg.sig ``` SDB@79
Do not able to install DMD Compiler with curl
The following there is error "No public key"! ``` md@SDB MSYS ~ $ curl -fsS https://dlang.org/install.sh | bash -s dmd Downloading https://dlang.org/d-keyring.gpg 100.0% Downloading https://dlang.org/install.sh 100.0% gpg: directory '/home/md/.gnupg' created gpg: /home/md/.gnupg/trustdb.gpg: trustdb created gpg: Signature made Mon Apr 1 23:02:30 2024 +03 gpg:using RSA key E22EC04C82780970381402F4A7D4D42F8EC6A355 gpg: Can't check signature: No public key Invalid signature https://dlang.org/install.sh.sig ``` How can I solve it? Thanks... SDB@79
Re: ImportC question
On Tuesday, 29 October 2024 at 20:26:58 UTC, DLearner wrote: On Tuesday, 29 October 2024 at 18:57:15 UTC, Salih Dincer wrote: DMD Compiler version? SDB@79 ``` C:\Users\SoftDev>dmd DMD64 D Compiler v2.106.0-dirty ``` First of all, be sure to get rid of that old version because a lot has changed since that version. There's no harm in having different VSlibs installed. The main problem is that Windows is crap. The address of the solution is: MSYS2. It's simple to install it on your computer and use it safely. Look, there are videos on this subject, here is one of them: https://youtu.be/OwQobefF-iE?si=QN8sp5SknSROXY83 Yes, now your problems will be solved, insha'Allah SDB@79
Re: ImportC question
On Monday, 28 October 2024 at 20:56:03 UTC, DLearner wrote: Just trying ImportC under Windows 10: ```c #include int main() { printf("Hello world.\n"); return 0; } ``` Produces ``` dmd hello.c failed launching cl.exe /P /Zc:preprocessor /PD /nologo hello.c /FIC:\D\dmd2\windows\bin64\..\..\src\druntime\import\importc.h /Fihello.i Error: C preprocess command cl.exe failed for file hello.c, exit status 1 ``` DMD Compiler version? SDB@79
Re: NGINX Unit and vibe.d Integration Performance
On Monday, 28 October 2024 at 20:53:32 UTC, Salih Dincer wrote: Semaphore? Please see: https://dlang.org/phobos/core_sync_semaphore.html SDB@79
Re: NGINX Unit and vibe.d Integration Performance
On Monday, 28 October 2024 at 19:57:41 UTC, Kyle Ingraham wrote: - Polling too little killed performance and too often wrecked CPU usage. - Using message passing reduced performance quite a bit. - Batching reads was hard because it was tricky balancing performance for single requests with performance for streams of them. Semaphore? https://demirten-gitbooks-io.translate.goog/linux-sistem-programlama/content/semaphore/operations.html?_x_tr_sl=tr&_x_tr_tl=en&_x_tr_hl=tr&_x_tr_pto=wapp SDB@79
Re: NGINX Unit and vibe.d Integration Performance
On Monday, 28 October 2024 at 01:06:58 UTC, Kyle Ingraham wrote: ... The second though only achieves ~20k requests per second. In that demo I try to make vibe.d's concurrency system available during request handling. NGINX Unit's event loop is run in its own thread. When requests arrive, Unit sends them to the main thread for handling on vibe.d's event loop. I've tried a few methods to increase performance... Apparently, vibe.d's event loop is not fully compatible with NGINX Unit's loop, causing performance loss. I wonder if it would be wise to use something like an IntrusiveQueue or task pool to make it compatible? For example, something like this: ```d alias IQ = IntrusiveQueue; struct IntrusiveQueue(T) { import core.atomic; private { T[] buffer; size_t head, tail; alias acq = MemoryOrder.acq; alias rel = MemoryOrder.rel; } size_t capacity; this(size_t capacity) { this.capacity = capacity; buffer.length = capacity; } alias push = enqueue; bool enqueue(T item) { auto currTail = tail.atomicLoad!acq; auto nextTail = (currTail + 1) % capacity; if (nextTail == head.atomicLoad!acq) return false; buffer[currTail] = item; atomicStore!rel(tail, nextTail); return true; } alias fetch = dequeue; bool dequeue(ref T item) { auto currHead = head.atomicLoad!acq; if (currHead == tail.atomicLoad!acq) return false; auto nextTail = (currHead + 1) % capacity; item = buffer[currHead]; atomicStore!rel(head, nextTail); return true; } } unittest { enum start = 41; auto queue = IQ!int(10); queue.push(start); queue.push(start + 1); int item; if (queue.fetch(item)) assert(item == start); if (queue.fetch(item)) assert(item == start + 1); } ``` SDB@79
Re: std.algorithm.countUntil and alias
On Wednesday, 23 October 2024 at 15:25:48 UTC, Salih Dincer wrote: If it were me, I would equip my type with aliases like below. But for some reason I don't understand, the enum Numbers works, while the enum Test which is of type string doesn't! I figured out why it wasn't working. It turns out I had made a size_t comparison with a string. In this case, it's smart to move away from string altogether and use alias fun(S). Here's D's perfect syntax: ```d struct Zoo(size_t i) { size_t count; static index = i; } void main() { enum Animal { dog = 3, cow, fox, cat } Animal[] animals; with(Animal) animals = [dog, cow, fox, cat]; alias myType = Zoo!(Animal.fox); alias fun(S) = e => e == S.index; import std.algorithm : countUntil; auto myStruct = myType( animals.countUntil!(fun!myType) ); assert(myStruct.index == 5); assert(myStruct.count == 2); import std.stdio; myStruct.writeln(": ", animals); // Zoo!5LU(2): [dog, cow, fox, cat] } ``` SDB@79
Re: std.algorithm.countUntil and alias
On Wednesday, 23 October 2024 at 12:32:09 UTC, Anton Pastukhov wrote: I'm struggling with this code. Why `countUntil` won't work with aliases? ```d import std.traits : EnumMembers; import std.algorithm : countUntil; enum Test: string { One = "one", Two = "two", Three = "three" } ``` If it were me, I would equip my type with aliases like below. But for some reason I don't understand, the enum Numbers works, while the enum Test which is of type string doesn't! ```d import std.traits : EnumMembers; import std.algorithm : countUntil; enum Test: string { One = "one", Two = "two", Three = "three" } enum Numbers: size_t { One = 1, Two, Three } struct MyStruct(T) { enum tMax = T.max; size_t idx; } alias myType = Numbers; // Test; // not works! void main() { alias myAlias = MyStruct!myType; auto rng = [EnumMembers!myType]; auto idx = rng.countUntil!(e => e == myAlias.tMax); auto myStruct = myAlias(idx); assert(myStruct.idx == 2); } ``` SDB@79
Re: std.algorithm.countUntil and alias
On Wednesday, 23 October 2024 at 12:46:24 UTC, Paul Backus wrote: On Wednesday, 23 October 2024 at 12:32:09 UTC, Anton Pastukhov wrote: There are two possible solutions to this. One is to make `MyStruct.test` a `static` variable: ```d // Solution #1 struct MyStruct { static Test test = Test.Three; } ``` The code also compiles like this. In this case, can we say that there are 3 solutions or are static and enum actually the same thing? ```d struct MyStruct { enum test = Test.Three } ``` SDB@79
Re: interfacing cpp
On Tuesday, 22 October 2024 at 10:50:22 UTC, f wrote: std.cpp -- ```c #include \ #include \ #include \ using namespace std; void a(string a) { cout\<\<" hello " \<\libstdc++ std::__cxx11::basic_string is not yet supported; the struct contains an interior pointer which breaks D move semantics! but with options AA="-D_GLIBCXX_USECXX11_ABI=0" on g++ , and BB="-version=_GLIBCXX_USE_CXX98_ABI" on dmd the message is : Error: undefined reference to `a(std::string)` how to solve the, std:string , std:vector, std:optional ? is there any article / links on general interfacing c++ problem solving ? thanks In C++, template classes and some STL constructs (e.g. std::basic_string) cannot be directly transferred to D because the compile-time mechanisms for templates in C++ are different from D. SDB@79
Re: Scope & Structs
On Friday, 18 October 2024 at 07:43:47 UTC, Richard (Rikki) Andrew Cattermole wrote: Sorry for not replying sooner, COVID has not been a fun virus for my mind to have. When a variable is declared with a struct that needs cleanup, it effectively rewrites the following statements into a try finally: ```d void main() { S s = 0; try { if (true) return 0; } finally s.~this(); return 0; } ``` Thank you for your answer. I also had a minor operation and I am fine now. I hope you are fine too. SDB@79
Re: Hola a todos, esta no es una pregunta, sino que estoy publicando los descubrimientos en Dlang en mi github
On Wednesday, 16 October 2024 at 23:54:45 UTC, Danico wrote: https://github.com/Alinarov/D-descubrimientos ¡Bienvenido (Bienvenida ?) a nuestro D Forum! Nos alegra mucho tenerte con nosotros. Es obvio que no estás empezando, y estamos seguros de que tu experiencia será de gran valor para todos. Pero es necesario escribir en inglés: Welcome to the world of D. It's obvious you're not just starting out. You will definitely get better with time. When I look at your code snippets, the first lines usually start like this: ```d #!/usr/bin/env dmd import std; alias print = writeln; //... ``` I'm sure you chose the print alias for convenience. But you can do something similar much more easily. Here it is: ```d import std.stdio : print = writeln; ``` This way selective importing makes it easier to learn the standard library and optimizes the compiled code in the best way possible. For example, the following function is very enjoyable to read: ```d auto maxPow(ulong a, ulong b) { import std.math : pow; import std.algorithm : min, max; auto power = a.min(b); return a.max(b).pow(power); } unittest { assert(maxPow(2, 5) == 25); assert(maxPow(5, 2) == 25); assert(maxPow(5, 0) == 1); assert(maxPow(0, 5) == 1); } ``` It may seem strange to you to use import lines inside functions, here, there, everywhere. But rest assured, this experience will provide you with advantages that are not available in almost any other programming language. Of course, the choice is yours, it is possible to make everything much easier with `import std`. 😁 SDB@89
Re: Scope & Structs
On Saturday, 12 October 2024 at 13:11:52 UTC, Richard (Rikki) Andrew Cattermole wrote: You are not wrong, when it is a struct, it is being heap allocated. Sorry for prolonging the topic. I am very curious about your answers along with your patience... Can we say that structs are in the stack (LIFO) as long as we do not use the new operator? Also, should using scope in structures cause a change? I never seen it does! However, there is no incompatibility here: Whether it is a class or a struct, when you use the new operator, the first run constructor becomes the first run destructor with FIFO logic. You can reverse this situation with scope (but only in classes). By reverse I don't mean LIFO! In fact, the correct expression is that when you are done with the object, it is removed. Thanks, SDB@79
Re: Scope & Structs
On Saturday, 12 October 2024 at 13:08:03 UTC, Nick Treleaven wrote: If you want stack allocation of structs, why use `new`? Actually, I almost never use the new operator except with(). I was surprised because it seemed inconsistent here and wanted to share my experiment. On Saturday, 12 October 2024 at 13:11:52 UTC, Richard (Rikki) Andrew Cattermole wrote: You are not wrong, when it is a struct, it is being heap allocated. Looks like the optimization for classes, hasn't been applied to structs. https://issues.dlang.org/show_bug.cgi?id=24806 So if `scope` is a facility for classes, it should give an error when used in structures. Is that so? I understand this from the issue you opened. SDB@79
Re: Scope & Structs
On Saturday, 12 October 2024 at 12:02:04 UTC, Salih Dincer wrote: ... even if I call the structure with the new operator. But if I stop using classes, scope doesn't work properly! Edit: It seems like scope is ineffective in structures. In fact, if there is the new operator, it is as if scope does not exist, and if it is construct without the new operator, it is as if scope does exist; is this normal? SDB@79
Scope & Structs
I have a small program like below. Everything works as it should in classes; even if I call the structure with the new operator. But if I stop using classes, scope doesn't work properly! ```d class/* STEP2 struct//*/ Foo { this(int i) { i.writefln!"Object %s is created..."; } ~this() { writeln("Object was deleted!"); } } import std.stdio; void main() { write("call "); writeln("return ", loop); } auto loop() { enum func = __FUNCTION__; func.writeln; for (auto i = 1; i != 3; ++i) { scope // STEP1 auto foo = new Foo(i); } return func; } ``` Please put a comment (//) mark at the beginning of the line that says STEP1 and then STEP2. Then change STEP1 back to its previous state, that is, enable the scope. You will sense that something is wrong... Why doesn't it work correctly in structs? Or is scope the default in structs? SDB@79
Re: (How) can reflection recoginzie `extern` variables?
On Friday, 11 October 2024 at 17:58:00 UTC, Salih Dincer wrote: There is no __traits mechanism to directly determine ... ```d extern int x; int y; pragma(msg, __traits(isSame, y, x)); ``` I tried it now, but as I said, it wouldn't be unreasonable: SDB@79
Re: (How) can reflection recoginzie `extern` variables?
On Friday, 11 October 2024 at 16:33:55 UTC, Quirin Schroll wrote: ```d extern int x; // int y; ``` (How) can I get the information that `x` is `extern` and `y` is not? There seems to be no `__traits` for it. There is no __traits mechanism to directly determine whether a symbol is extern. However, the extern linkage is determined at compile time based on how the symbol is defined, and the type of linkage it uses is determined by the compiler. SDB@79
Re: Accessing __traits(identifier) for variadic function arguments
On Friday, 11 October 2024 at 03:01:54 UTC, Alexa Schor wrote: Hello! I've been working on building some debug print functions and have been using the `__traits(identifier, x)` to get the name of parameters passed into a function, trying as best I can to replicate the functionality of the useful C++ [`#` operator](https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html) to turn a macro argument into a string literal. This works fine for a single aliased argument ```d void printName(alias val)() { writeln(__traits(identifier, val)); } ``` but I wanted to see if I could get it working in a variadic function. However, attempting with a static foreach, it seems that the `__traits(identifier)` value is not preserved: ```d void printNames(T...)(T args) { static foreach(val; args) writeln(__traits(identifier, val)); } ``` Instead, ```d void main() { float x = 123; float y = 456; printName!(x); printName!(y); printNames(x, y); } ``` yields ```d x y __param_0 __param_1 ``` *(I guess this makes sense, as it's no longer a aliased template argument and now is a function argument, although I thought I remember reading that variadic function arguments were aliased?)* I suppose my question is: is there any way to determine the original name of a value passed into a variadic function, in the way that the `printName` function above does? I'm quite new to this language, so I very much apologize if this question is ill-formed or based on incorrect assumptions. I also realize this is a weird application, so I wouldn't be too surprised if this just isn't possible, but I figured I'd ask here. Thank you, Alexa ```d import std.stdio, core.interpolation; void show(Args...)(InterpolationHeader hdr, Args args, InterpolationFooter ftr) { foreach (arg; args) { static if (is(typeof(arg) == InterpolatedExpression!code, string code)) code.write; else static if (is(typeof(arg) == InterpolatedLiteral!str, string str)) str.write; else write(" = ", arg); } writeln(); } void main() { int a = 5, b = 22; show(i`$(a), $(b), $(a + b)`); // a = 5, b = 22, a + b = 27 } ``` SDB@79
Re: Wrapper for PAM
On Thursday, 10 October 2024 at 12:58:22 UTC, Salih Dincer wrote: ```d class Auth { private: struct PAMdata { string password; string newPassword; } extern(C) { // 1. Salih changed it: static int conversation_func(int num_msg, const pam_message **msg, pam_response **resp, void *appdata_ptr) { auto data = cast(PAMdata*)appdata_ptr; auto responses = cast(pam_response*) calloc(num_msg, pam_response.sizeof); if (responses == null) { return PAM_BUF_ERR; } for (int i = 0; i < num_msg; ++i) { responses[i].resp_retcode = 0; switch (msg[i].msg_style) { case PAM_PROMPT_ECHO_ON: goto case; case PAM_PROMPT_ECHO_OFF: switch (msg[i].msg.to!string) { case "New password: ": goto case; case "Retype new password: ": responses[i].resp = strdup(data.newPassword.toStringz); break; case "Password: ": goto case; case "Current password: ": responses[i].resp = strdup(data.password.toStringz); break; default: responses[i].resp = null; break; } break; default: responses[i].resp = null; break; } } *resp = responses; return PAM_SUCCESS; } } public: int authenticate(string username, string password) { if (!username.length) { return AUTH_ERR_USER; } if (!password.length) { return AUTH_ERR_PASS; } pam_handle_t *pamh = null; PAMdata data = { password }; void *appdata_ptr = &data; // 2. Salih changed it: pam_conv conv = { cast(conversation*)&conversation_func, appdata_ptr }; // 3. Salih changed it: auto retval = pam_start("login", username.toStringz, &conv, &pamh); if (retval != PAM_SUCCESS) { return AUTH_ERR_START; } retval = pam_authenticate(pamh, 0); if (retval != PAM_SUCCESS) { pam_end(pamh, retval); return AUTH_ERR_AUTH; } retval = pam_end(pamh, PAM_SUCCESS); if (retval != PAM_SUCCESS) { return AUTH_ERR_END; } return AUTH_SUCCESS; } } ``` SDB@79
Re: Wrapper for PAM
On Monday, 7 October 2024 at 08:23:08 UTC, Alexander Zhirov wrote: I tried to build a class with a private function `conversation_func` to call it inside the public authentication function. When compiling I get this message: ``` source/login/auth.d(87,46): Deprecation: casting from extern (C) int delegate(int num_msg, const(pam_message**) msg, pam_response** resp, void* appdata_ptr) to extern (C) int function(int, const(pam_message**), pam_response**, void*)* is deprecated ``` And when I start up, at the moment of calling the authentication function, I get `Segmentation fault`. Is the function identified differently in the class? How can this be fixed? Would you try static this? ```d // 1. Salih changed it: extern(C) static int conversation_func(int num_msg, const pam_message **msg, pam_response **resp, void *appdata_ptr) { /* ... */} ``` There is no need for `this`. ```d // 2. Salih changed it: pam_conv conv = { cast(conversation*)&/*this.*/conversation_func, appdata_ptr }; ``` SDB@79
Re: Integer types
On Tuesday, 8 October 2024 at 15:57:24 UTC, Jared McKinnan wrote: Hello there, Just wanted to ask if there's a real difference between e.g. the "long" type and "int_fast64_t" in terms of execution times. Thanks ```int_fast64_t``` is the fastest 64-bit or larger integer type. The type that is at least 64 bits long and works fastest on the platform is selected. This type can be selected if performance is more important than memory and the processor can run faster on certain types. ```long``` is an integer that is strictly 64 bits long. That is, this type is permanently 64 bits and provides cross-platform portability. If you want strictly 64 bits and care about cross-platform consistency, you should use this type. So you have to choose between consistency and efficiency. When you tell the compiler this choice, it implements it if it can agree with the processor. SDB@79
Re: Why is this not allowed?
On Monday, 7 October 2024 at 17:20:00 UTC, ryuukk_ wrote: We went from trying to do that: ```d struct EntityDef { struct { int hp; } stats; } ``` to getting suggested to do that instead: ```d struct Foo { int bar; //struct {/* Baz baz; struct Baz { auto opAssign(int value) => baz = value;//*/ int baz; } } void main() { Foo foo; foo.bar = 7; foo.baz = 42; imported!"std.stdio".writeln(foo); /* with opAssign() Anonymous Foo(7, Baz(42)) or Foo(7, 42)*/ } ``` I understand you, but you misunderstood me. You probably brought up a problem that can't be solved quickly (or ever). I wanted to acknowledge D's praise and bring a different perspective. Would this solution work for you? ```d template Foo() { int hp; } struct EntityDef { mixin Foo stats; } void main() { auto num = EntityDef(41); assert(num.stats.hp == 41); with(num) { stats.hp = 42; assert(stats.hp == 42); } } ``` SDB@79
Re: Why is this not allowed?
On Saturday, 5 October 2024 at 06:35:57 UTC, ryuukk_ wrote: No, i don't want to do: ```C struct EntityDef { struct Stats { int hp; } stats; } ``` Repeating the same name 3 times, i should go back to the stone age too no? C and all other C like languages allow me to be concise Why is it a D thing to be backward? In the coding scheme, fields/members/methods may be at the beginning, middle, or end of the structure, or may not be identifiers to the right of the anonymous structs. In structures, a lot (I wish it was in bitfield) has been taken from C. Especially not using typedef and not having extra semicolons make D stand out even with these. As for anonymous structures, they have to be like this in order to be used with unions. I think everything is as it should be, and even more: Please include the relevant comment line (the // characters next to the anonymous struct) in the code and be amazed by the change :) ```d struct Foo { int bar; //struct {/* Baz baz; struct Baz { auto opAssign(int value) => baz = value;//*/ int baz; } } void main() { Foo foo; foo.bar = 7; foo.baz = 42; imported!"std.stdio".writeln(foo); /* with opAssign() Anonymous Foo(7, Baz(42)) or Foo(7, 42) */ } ``` Thank you to the creators and maintainers of the D. SDB@79
Re: How to evaluate a JSON file at compile time and create a struct out of it?
On Friday, 4 October 2024 at 08:45:49 UTC, holyzantaclara wrote: Hello hello everyone ^_^, I am new in D, and started this morning. I found a way to read a file at compile time with `-J.` and `static string content = import("my_json_file.json")` https://dlang.org/spec/expression.html#import_expressions
Re: Wrapper for PAM
On Friday, 4 October 2024 at 12:39:45 UTC, Alexander Zhirov wrote: On Thursday, 3 October 2024 at 23:56:37 UTC, Salih Dincer wrote I meant taking the function to D for the elements of the C syntax. To get only an API to which we can pass our callback, and hide everything else inside the wrapper. I have no experience porting from C to D, but I would like to try to learn the basics to make a small library for PAM. https://dlang.org/spec/importc.html
Re: Wrapper for PAM
On Thursday, 3 October 2024 at 22:54:53 UTC, Alexander Zhirov wrote: I want to try to make access via D to PAM. ```d /// I added it here: import pam_wrapper; int main(string[] args) { if (args.length < 3) { writeln("Usage: ", args[0], " "); return 1; } /// I added it here. string username = args[1]; string password = args[2]; int result = authenticate_user(username, password); if (result == 0) { writeln("Authentication succeeded!"); } else { writefln("Authentication failed with code: %d", result); } return EXIT_SUCCESS; } ``` It is possible to implement PAM (Pluggable Authentication Modules) support in the D programming language using the standard library. The D standard library provides extern(C) support to access C language APIs and a strong FFI (Foreign Function Interface) support to adapt to C data structures. However, D itself does not include a special module for PAM, so it is necessary to work with C-based PAM libraries in the D language. I think you should use 2 separate modules! This can make type conversions and memory management safer. Here is the pam_wrapper.d file: ```d module pam_wrapper; import pam; // You have this module. import std.string, std.conv : to; import core.stdc.string : strdup; import core.stdc.stdlib : malloc, free; public import std.stdio; struct pam_data { string password; } extern(C) { int conversation_func(int num_msg, const pam_message **msg, pam_response **resp, void *appdata_ptr) { pam_data *data = cast(pam_data*)appdata_ptr; *resp = cast(pam_response *)malloc(num_msg * pam_response.sizeof); if (resp == null) return PAM_BUF_ERR; for (int i = 0; i < num_msg; i++) { switch (msg[i].msg_style) { case PAM_PROMPT_ECHO_ON: goto case; case PAM_PROMPT_ECHO_OFF: resp[i].resp = strdup(data.password.toStringz); resp[i].resp_retcode = 0; break; default: resp[i].resp = null; resp[i].resp_retcode = 0; break; } } return PAM_SUCCESS; } } int authenticate_user(string username, string password) { pam_handle_t *pamh = null; int retval = 0; pam_data data = { password }; void *appdata_ptr = &data; pam_conv conv = { cast(conversation*)&conversation_func, appdata_ptr }; retval = pam_start("login", username.toStringz, &conv, &pamh); if (retval != PAM_SUCCESS) { pam_strerror(pamh, retval).to!string.writefln!"pam_start: %s"; return 1; } retval = pam_authenticate(pamh, 0); if (retval != PAM_SUCCESS) { pam_strerror(pamh, retval).to!string.writefln!"Authentication failure: %s"; pam_end(pamh, retval); return 2; } retval = pam_end(pamh, PAM_SUCCESS); if (retval != PAM_SUCCESS) { pam_strerror(pamh, retval).to!string.writefln!"pam_end: %s"; return 3; } return 0; } ``` SDB@79
Re: Templates considered impressive
On Tuesday, 1 October 2024 at 17:30:20 UTC, H. S. Teoh wrote: On Tue, Oct 01, 2024 at 04:30:27PM +, Salih Dincer wrote: Please add this to your MyCon structure: ```d alias value this; // assert(num1 == 3.14); ``` And test it like this too, I think it's awesome! [...] IMO it's not a good idea to recommend the use of `alias this`. It's a neat trick that solves the short-term problem... You may be right about the alias. Let's go a little further and put the convertToHex() function between the template and the struct: ```d template MyCon(T, string str = "0") { MyCon convert = str; struct MyCon { T value; //alias value this; this(R)(R data) { import std.conv : to; value = data.to!T; } mixin DownRange; } enum _input = str; string convertToHex() { import std.string : format; return _input.format!"%-(%02X%)"; } } import std.stdio; void main() { mixin MyCon!(double, "3.141") piNumber; piNumber.convertToHex().write(": "); piNumber.convert.writeln; auto iNumber = MyCon!double("0.123"); piNumber.convertToHex().write(": "); iNumber.value.writeln; // mixin MyCon!(int, "123") testError; mixin myStatement!(int, "Hello"); assert(_value == 42); // no error mixin myStatement!(double, "D!"); // assert(_value == 42); } template myStatement(T, string value = "") { auto doIt() { T.stringof.writeln(": ", value); return 42; } auto _value = doIt(); } template DownRange() { auto empty() => value <= 0; auto front() => value; auto popFront() => --value; } struct S { int value; mixin DownRange; } ``` I also added another template called DownRange (InputRange functions) inside a template. Since the structures of this mixin are static codes, unfortunately everything looks like const and cannot be changed. Please play around in the [playground](https://run.dlang.io/). I tried to show many things in the code above. Here is the output of the code: ```d /* 332E313431: [3.141, 2.141, 1.141, 0.141] 332E313431: 0.123 int: Hello double: D! */ ``` Please note iNumber, not piNumber. SDB@79
Re: Templates considered impressive
On Tuesday, 1 October 2024 at 16:18:17 UTC, Salih Dincer wrote: ```d // ... struct MyCon { string input; T value; this(string data) { // ... } // ... } } ``` Please add this to your MyCon structure: ```d alias value this; // assert(num1 == 3.14); ``` And test it like this too, I think it's awesome! SDB@79
Re: Templates considered impressive
On Tuesday, 1 October 2024 at 01:00:08 UTC, Andy Valencia wrote: ... A conversion like: auto d = atoi!double("123.456"); is about 4k of code. Nice! Congratulations on your initiative. D is very flexible with templates, especially with the mixin templates. For example, you might like this one: ```d template MyCon (T, string str = "0") { MyCon init = str; struct MyCon { string input; T value; this(string data) { import std.conv : to; value = data.to!T; input = data; } string toString() => input; string convertToHex() { import std.string : format; return input.format!"%-(%02X%)"; } } } import std.stdio; void main() { //mixin MyCon!int;/* mixin MyCon!int zero; // There is an invisible object here: init (struct MyCon) zero.init.writeln; //* 0 */ // Here is a new object: MyCon!double num1 = "3.14"; num1.writeln; // 3.14 assert(num1.value == 3.14); // and a convenience function... :) num1.convertToHex.writeln; assert(num1.convertToHex == "332E3134"); } ``` SDB@79
Re: Adapting foreign iterators to D ranges
On Thursday, 25 April 2024 at 03:18:36 UTC, cc wrote: On Wednesday, 24 April 2024 at 05:08:25 UTC, Salih Dincer wrote: Yes, `opApply()` works! You just need to use `do while()` instead of `while()` because it skips the first item. It depends on the type of structure being consumed, if it provides "next" as a direct pointer then yeah you would need to consume the item first before iterating to the next in line. However some APIs provide an opaque iterator type where you call a "next" method to get the first element, IIRC Lua does something like this. I've noticed a strange behavior in the Range structure that consumes the List class! If we use foreach(), we should take a backup as we're used to, or use the rewind() function as I did below. These days, I've started to delve deeper into the opApply() feature. I wanted to fix this mistake I made in the past. ```d struct Range { private List list; int opApply(scope int delegate(Node* t) dg) { while(auto current = list.Next) { if (auto r = dg(current)) return r; } list.rewind(); return 0; } } ``` Also, due to the nature of linked lists, we cannot print the number 1 added at the beginning with foreach(). Therefore, when creating the List class, it may be wise to create it without giving any parameters and start adding elements from 1. You might also be interested in this topic about opApply: https://forum.dlang.org/thread/jxzqsxasierzokgcy...@forum.dlang.org SDB@79
Perfect: using foreach with more...
😁 Try the 2nd usage, D is a very flexible language; moves towards perfection! ```d struct Sarma { int i; // mixin DownRange; } struct Foo(T) { int[] array; // 1. USAGE auto opApply(scope int delegate(T) dg) { foreach (ref e; array) { auto result = dg(T(e)); } return 0; } auto opApply(scope // 2. USAGE int delegate(size_t, int, ref int) dg) { int count; foreach (i, ref e; array) { e *= 15; ++count; auto result = dg(i, count, e); } return 0; } } import std.stdio; void main() { auto foo = Foo!Sarma( [2, 4, 6] ); foreach (Sarma e; foo) { e.write(" "); } writeln; foreach (i, s, ref e; foo) { s.writef!"counter = %s, "; i.writeln(": ", e++); } foo.array.writeln; } template DownRange() { bool empty() { return i <= 0; } auto front() { return i; } void popFront() { --i; } } ``` It may be explained in specific documentation (on 12.11.11). https://dlang.org/spec/statement.html#foreach_over_arrays SDB@79
Re: Integer precision of function return types
On Friday, 27 September 2024 at 20:28:21 UTC, H. S. Teoh wrote: ... The reason for (2) is that in UFCS chains, the only thing you really only care about is what kind of range it is that you're dealing with, and maybe the element type. What exactly the container type is, is unimportant, and in fact, stating it explicitly is detrimental to maintenance because the library that gave you that type may change the concrete type in the future while retaining the same range and element type. So by naming an explicit type for the range, you introduce a potential needless breakage in your code when you next upgrade the library. Instead, use `auto` to let the compiler figure out what the concrete type is, as long as it conforms to the expected range semantics and has a compatible element type, your code will continue to work as before. ... Once my range didn't work because I used **auto** instead of **bool** in the standard InputRange functions (I think it had something to do with **length()** too...). As I said, I'm not sure, it could also be **size_t length()**. So there are subtle cases where we should use auto, I wish I could show you but I can't think of any. SDB@79
Re: Integer precision of function return types
On Thursday, 26 September 2024 at 06:53:12 UTC, Per Nordlöw wrote: Should a function like ```d uint parseHex(in char ch) pure nothrow @safe @nogc { switch (ch) { case '0': .. case '9': return ch - '0'; case 'a': .. case 'f': return 10 + ch - 'a'; case 'A': .. case 'F': return 10 + ch - 'A'; default: assert(0, "Non-hexadecimal character"); } } ``` instead return an ubyte? When I use standard library facilities, I try to use ubyte; for example: (See "toggle comment" in the section...) ```d void parseFromHexString(R)(out R hex, const(char)[] str) { import std.algorithm : map, copy; import std.conv : to; import std.range : front, chunks; alias T = typeof(hex.front); str.chunks(T.sizeof * 2) .map!(bin => bin .to!T(16)) .copy(hex[]); } import std.stdio; void main() { enum hex = "48656C6C6F2044202620576F726C6421"; enum size = hex.length / 2; auto sample = imported!"std.conv".hexString!hex; sample.writeln; // Hello D & World! enum hexStr = x"48656C6C6F2044202620576F726C6421"; hexStr.writeln; // Hello D & World! assert(is(typeof(hexStr) == string)); immutable int[] intStr = x"48656C6C6F2044202620576F726C6421"; intStr.writeln; // [1214606444, 1864385568, 639653743, 1919706145] int[size] buf; buf.parseFromHexString(hex); buf.writeln; //char[size] buff; /* ubyte[size] buff;/* please toggle comment with above */ buff.parseFromHexString("BADEDE"); buff.writeln; ``` But when I try to do something with my own functions, I have control and I do what I want. You can also use char below, ubyte is not a problem either: ```d auto toHexDigit(char value) { if(value > 9) value += 7; return '0' + value; } auto toHexString(R)(R str) { string result; char a, b; foreach(char c; str) { a = c / 16; b = c % 16; result ~= a.toHexDigit; result ~= b.toHexDigit; } return result; } void main() { assert(sample.toHexString == hex); } ``` SDB@79
Re: How to escape control characters?
On Thursday, 19 September 2024 at 14:30:08 UTC, Gerardo Cahn wrote: On Wednesday, 24 August 2022 at 08:12:33 UTC, Salih Dincer wrote: On Tuesday, 23 August 2022 at 23:17:21 UTC, Salih Dincer wrote: ... Actually, both structures could be combined: ```d struct EscapedString { string[1] str; this(string str) @nogc pure nothrow @safe { ...(rest clipped) ``` Thanks to all. I am using the code listed here. I can't but feel like Salieri with Mozart: I know enough D to appreciate this thread, but not enough to create this on my own... This must be a metaphor, from the past... I would like to thank you for saying "hello" to the silence. Thanks to you, I have just developed the missing parts of the code. I am sure that if the silent majority criticized such codes, the field would be beautiful. I hadn't thought about UTF codes before, they seem to work. What do you think? ```d import std.stdio; void main() { enum str = r"\tHello\xfeD\r\nProgramming\0\nWorld!\b\f"; auto u = str.unescaped(); auto e = u.escaped(); assert(e == str); u.unescaped.writeln; } auto escaped(string str) { import std.algorithm : map; import std.conv : to, toChars; import std.string : format; return str.map!(chr => () { auto code = chr.to!ulong; if (code >= 0x7f) { return code.toChars!(16, char) .format!"\\x%-(%c%)"; } switch (code) { case '\0': return `\0`; case '\b': return `\b`; case '\f': return `\f`; case '\t': return `\t`; case '\n': return `\n`; case '\r': return `\r`; case '"': return `\"`; case '\'': return `\'`; case '\\': return `\\`; //case ' ': return `\s`; default: return chr.to!string; } }()).format!"%-(%s%)"; } string unescaped(string str) { import std.format : fs = FormatSpec; import std.format : uv = unformatValue; fs!char f; auto s = `["` ~ str ~ `"]`; return uv!(string[])(s, f)[0]; } ``` SDB@79
Re: Is it possible to use templates to implement something like the `@show` macro from the Julia programming langauge in D?
On Wednesday, 11 September 2024 at 22:06:54 UTC, WB wrote: Honestly, D, does not really need it, and most of solutions (like above) do have one or few limitations and drawbacks. Some will be acceptable in some projects, some not. There is plenty of stuff in language and library already, adding small things like that are not really the best thing. There is plenty of very successful languages, that do not offer this (Go, C++, Python 3.5 and earlier, Lua, older JavaScript, etc) and just adding it will not make D automatically more successful. I feel there is too much already in D and standard library, and things are added to quickly and eagerly, and years later we end up in a mess that cannot be solved (because of compatibility). Yes, I agree; what I see is a very complicated Phobos2. Because it has become like this over time and submodules have been developed to eliminate the confusion. For example, there are things in std.math that we do not use often, a very basic algorithm like gcd() is expected to be written in std.numeric or the factorial() function by you. In short, Phobos3 will adapt better to the language for beginners if it is written systematically from the beginning; std.math should be reorganized from scratch. SDB@79
Re: assert
On Wednesday, 11 September 2024 at 04:01:53 UTC, f wrote: i mean , is this a bug? This is not a bug. The problem is due to a misunderstanding of the -release parameter. The following related topic opened by Steven and the answers given by Walter are really valuable: https://forum.dlang.org/thread/pkeasakdbugctqdye...@forum.dlang.org SDB@79
Re: Is it possible to use templates to implement something like the `@show` macro from the Julia programming langauge in D?
On Wednesday, 11 September 2024 at 18:29:39 UTC, WB wrote: This code is about 13 years old, but still works. (It is functional and works, but I never it used more than what is in this repo). But now that we have interpolation sequences in the language, it would be way easier, cleaner and more powerful to use them. ```d assert(echo2("T $i, b, ${i-2}") == "writefln(\"T \", i, \", b, \", (i-2));\n"); ``` It looks clean and understandable. What is not understandable is that it has not been included in std.stdio for over 10 years. I know, string interpolation has just been integrated, but why hasn't something like this been developed in 10 years that would have no side effects and would attract the attention of beginners? SDB@79
Re: Is it possible to use templates to implement something like the `@show` macro from the Julia programming langauge in D?
On Monday, 9 September 2024 at 20:52:09 UTC, WraithGlade wrote: In any case, this version seems more brittle than the others at least After all, you will need it in 2 ways: 1. to learn, 2. to test. After testing, you can disable it with just the version parameter while compiling. It is even possible to turn it on/off by embedding ```// version = logOn; in the code and removing the comment feature. For this, embed VERSION(logOn) in the relevant lines... SDB@79
Re: Is it possible to use templates to implement something like the `@show` macro from the Julia programming langauge in D?
On Monday, 9 September 2024 at 17:56:04 UTC, monkyyy wrote: auto parse(char[] s)=>s[9..$-2]; void show(T,string file= __FILE__,int line=__LINE__)(T t){ writeln(File(file).byLine.drop(line-1).front.parse," == ",t); } void main(){ int i=3; show(i++ + ++i * i); show(i); } This solution is really successful. I didn't think there could be any other solution than mixin(); this is utterly ingenious! There is a working version of the code below and different tests. My only concern is why i == 5 in the line below when i == 28? ```d import std; auto parse(char[] s) => s[9..$ - 2]; void show(string file = __FILE__, int line = __LINE__, T)(T t) { File(file).byLine .drop(line-1) .front .parse .writeln(" == ", t); } template f(ulong n) { static if(n < 2) const f = 1; else const f = n * f!(n - 1); } void main() { int i = 3; show(i++ + ++i * i); show(i); T factorial(T)(T n)=>n<2?1:n*factorial(--n); show(factorial(10)); show(f!10); } /* Prints: i++ + ++i * i == 28 i == 5 factorial(10) == 3628800 f!10 == 3628800 */ ``` SDB@79
Re: Tuple List
On Wednesday, 4 September 2024 at 08:58:34 UTC, Sergey wrote: Something like: ```d l2.byPair.filter!"a.value > 0".map!(a => a.key).writeln; ``` Thank you for your answers, my forum friends. For tuples that are not fully integrated into the language yet, byPair() is a nice possibility. Because you don't need to import std.typecons. Moreover, instead of a complicated syntax, associative array makes life easier. Here is an example: ```d import std.range, std.algorithm, std.stdio; void main() { //import std.array : byPair;/* import std.typecons : Tuple; alias T = Tuple!(string, "key", int, "value"); auto list = [T("Mutfak", 41), T("WC", 0), T("Salon", 42), T("Atelye", 0) ]; list.map!"a.key".writeln; // ["Mutfak", "WC", "Salon", "Atelye"] ✓ /*/ auto list = ["Mutfak": 41, "WC": 0, "Salon": 42, "Atelye": 0 ]; list.byPair.map!"a.key".writeln; // ["WC", "Mutfak", "Atelye", "Salon"] ❓ // but the order is uncertain! //*/ } ``` SDB@79
Re: Tuple List
On Wednesday, 4 September 2024 at 08:04:58 UTC, drug007 wrote: You should use filter instead of find. Find finds the first element and returns the range from that first element to the end of the original range. Thank you, it's my mistake. We confused HOF, which has the same first letter. So, if we turn the question towards the associative array, can a similar one be done without using each or foreach? For example: ```d auto l2 = ["WC": 0, "Mutfak": 41, "Salon": 42, "Atelye": 0 ]; l2.values.filter!"a > 0".writeln; // [41, 42] foreach(key, value; l2) if(value > 0) key.write(", "); // Mutfak, Salon, ```
Tuple List
Why doesn't t2 give the same result as t1? ```d import std.algorithm; import std.typecons; alias T = Tuple!(string, "key", int, "value"); auto t1 = [T("WC", 0), T("Atelye", 0), T("Mutfak", 41), T("Salon", 42) ]; assert(t1.find!"a.value > 0" .map!"a.key" .equal(["Mutfak", "Salon"]) ); auto t2 = [T("WC", 0), T("Mutfak", 41), T("Salon", 42), T("Atelye", 0) ]; assert(t2.find!"a.value > 0" .map!"a.key" .equal(["Mutfak", "Salon", "Atelye"]) ); ```
Re: D feature request
On Sunday, 4 August 2024 at 10:06:49 UTC, aberba wrote: So if I have a feature request, but I don't have the necessary technical skills to draft a DIP with the implementation details, is there a process in D community to submit such a request? please continue here: https://forum.dlang.org/group/dip.ideas SDB@79
Re: Octal Prime Numbers (challenge)
On Tuesday, 25 June 2024 at 06:44:28 UTC, Salih Dincer wrote: I'm not sharing the code for now because it's a challenge. Since we couldn't get a code snippet, I'd like to share some framing code without answers: ```d struct SumPrimes(size_t size) { import std.bigint; auto next = BigInt(1); auto power = BigInt(4); size_t index; auto empty() => index > size; auto front() => next + power; auto popFront() { // ... index++; } } unittest { for (auto p = SumPrimes!10(); !p.empty; p.popFront()) { auto n = p.front(); if (n.isPrime) { n.writef!"%11o: "; n.writeln(", ", p.index); } } } ``` SDB@79
Octal Prime Numbers (challenge)
Hello, I discovered something about octal prime numbers. I don't know if anyone has dealt with this before, but thanks to the power of the D programming language, it was very easy. So, by defining a range with the empty(), front() and popFront() functions, I produced an output, something like this: ~ dmd main.d -ofmain.out ~ ./main.out 0005: 5, 0 0045: 37, 1 0445: 293, 2 4445: 2341, 3 4445: 9586981, 7 0045: 613566757, 9 0445: 4908534053, 10 4445: 658812288346769701, 19 ... 4...4445: ? (hint: greater than 100 bits) In order, they are as follows "octal: decimal, and number of repetitions (¹⁰¹) and they are all prime 8 numbers! So what's the ninth? I'm not sharing the code for now because it's a challenge. But you should use std.bigint module and simply shift left and add octal 4 or binary 101. SDB@79
Re: How to generate a random number from system clock as seed
On Saturday, 8 June 2024 at 18:25:20 UTC, drug007 wrote: ```d { const seed = castFrom!long.to!uint(Clock.currStdTime); auto rng = Random(seed); auto result = generate!(() => uniform(0, 10, rng))().take(7); // new random numbers sequence every time result.writeln; } ``` If UnixTime is desired, it is sufficient to have currTime.toUnixTime instead of currStdTime. It will not reset until January 19, 2038. ```d auto seed = to!uint(Clock.currTime.toUnixTime); ``` SDB@79
Re: How to generate a random number from system clock as seed
On Saturday, 8 June 2024 at 13:19:30 UTC, Eric P626 wrote: I just want the number of seconds elapsed since jan 1st 1970. In other words, the internal system clock value. #unix #time @SDB79
Re: modInverse & powMod
On Friday, 7 June 2024 at 13:43:29 UTC, Salih Dincer wrote: SDB@79 I have only one question: Is there a modInverse() function in the standard library for use in RSA? Apparently not, it fell to lot :) I already had such a function... ```d auto modInverse(T)(T m, T n) pure { T q, ilk = n; T y, tmp, x = 1; while (m > 1) { q = m / n; tmp = n; n = m % n; m = tmp; tmp = y; y = x - q * y; x = tmp; } return x < 0 ? x + ilk : x; } ``` And in the BigInt module there was divMod() next to powmod(): ```d auto modInverse(BigInt a, BigInt m) { BigInt q, m0 = m; BigInt tmp, y, x = 1; while (a > 1) { // m is remainder now tmp = m; divMod(a, m, q, m); // process same as Euclid's algorithm a = tmp; tmp = y; // Update y and x y = x - q * y; x = tmp; } // Make x positive if (x < 0) x += m0; return x; } ``` Is PR required? Why not modInverse too! SDB@79
modInverse & powMod
I know there is modular exponentiation [std.math.exponential.powmod](https://dlang.org/library/std/math/exponential/powmod.html) in the standard library.While it works great in Pyrhon (even with very large numbers), it doesn't work with signed numbers in D. That's why I turned to the alternative below. Don't let it be misunderstood, I don't want to wear out the D language, I use whatever I have, I love D and I don't ask why it works so strangely. ```d //import std.math.exponential : fpowmod = powmod; /* T fpowmod(T)(T base, T exponent, T modulus) { auto r = T(1); for (T x = base, y = exponent; y; x = x * x % modulus, y /= 2) if (y % 2) r = r * x % modulus; return r; }//*/ ``` Thanks... SDB@79 I have only one question: Is there a modInverse() function in the standard library for use in RSA? I did research on this subject within the relevant modules. I guess not these? * [std.mathspecial.logmdigammaInverse](https://dlang.org/phobos/std_mathspecial.html) * [std.numeric.inverseFft](https://dlang.org/library/std/numeric.html)
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: Also try the code I gave in this thread: https://forum.dlang.org/post/fgzvdhkdyevtzznya...@forum.dlang.org In fact, please use this facility in the standard library: https://dlang.org/phobos/std_datetime_stopwatch.html#benchmark SDB@79
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? I know you want FIFO, I usually keep this on hand for fixed size LIFO; It can easily convert to FIFO and doesn't use LinkedList: ```d class LIFO(T) { T * element; size_t length, size; this(size_t s) { element = cast(T*)new T[s]; length = s; } auto rewind() => size = length; bool empty() => !size; auto front() => element[size - 1]; auto popFront() => --size; auto pop() => empty ? T(0) : element[--size]; alias push = insertFront; auto insertFront(T value) in(size < length, "Stack is overflow!") => element[size++] = value; auto ref opDollar() => length; auto ref opIndex(size_t i) => element[i]; auto ref opSlice(size_t first, size_t last) => element[first..last]; } unittest { enum test = 7; auto stack = new LIFO!size_t(test); assert(!stack.size); foreach (prime; 1..test + 1) { stack.insertFront(prime); } assert(stack.size == test); // == 7 stack.writeln(": ", stack.length); // [7, 6, 5, 4, 3, 2, 1]: 7 stack[$/2].writeln("-", stack[0]); // 4-1 stack.rewind(); stack.size.write(": ["); // 10: while (auto next = stack.pop) { if (next == 1) next.writeln("]"); else next.write(", "); } stack.size.writeln; // 0 stack.rewind(); assert(stack.size == test); } SDB@79
Re: Challenge Tuples
On Wednesday, 1 May 2024 at 14:15:19 UTC, Andrey Zherikov wrote: Shorter and without allocations: ```d import std.typecons : tuple; import std.algorithm : sum, each; auto sum(int i) => i; void main() { auto t = tuple(1, 2, 3, [1, 3], 5); int res=0; t.each!(e => res += sum(e)); assert(res == 15); } ``` Super! In summary, D is clearly ahead of the tuple. Especially with its features similar to AliasSeq, I think it is unrivaled. Wouldn't it be great if there was a feature that worked at runtime... SDB@79
Re: Challenge Tuples
On Saturday, 27 April 2024 at 15:36:40 UTC, Nick Treleaven wrote: On Saturday, 27 April 2024 at 15:32:40 UTC, Nick Treleaven wrote: On Saturday, 27 April 2024 at 11:55:58 UTC, Basile B. wrote: foreach const e in u do if echo(is, e, T) do result += e; static if (is(typeof(e) == int)) r += e; Actually I would write that: ```d R r; foreach (e; v) { static if (is(typeof(e) : R)) ``` I like the new sum() function, great Nick! Moreover, it also works with an ordinary range: ```d enum limit = 100; // sum = 5050 iota(limit + 1).sum.writeln; ``` Python seems too complicated to me, but C# looks delicious. Moreover, it was implemented without defining IEnumerator. Well done Matheus! SDB@79
Challenge Tuples
You have a 5-item data tuples as Tuple(1, 2, 3, [1, 3], 5) and implement the sum (total = 15) with the least codes using the sum() function of the language you are coding... Let's start with D: ```d import std.typecons : tuple; import std.algorithm : sum; void main() { auto t = tuple(1, 2, 3, [1, 3], 5); int[] arr; t.each!(e => arr ~= e); assert(arr.sum == 15); } ``` and bonus: ```d import std.typecons : tuple; import std.stdio : writeln; void main() { auto t = tuple(1, 2, 3, [1, 3], 5); auto results = [0]; foreach (data; t) { static if (is(typeof(data) == int[])) { int sum; foreach (d; data) { sum += d; } results ~= sum; } else { results ~= data; } } results.writeln; // [0, 1, 2, 3, 4, 5] ``` I bet you won't be able to do it this easily with other languages! Note: I tried with C# and Python and it didn't work! SDB@79
Re: Adapting foreign iterators to D ranges
On Tuesday, 23 April 2024 at 06:02:18 UTC, cc wrote: Just to offer an alternative solution (since it sometimes gets overlooked), there is also the `opApply` approach. You don't get full forward range status, and checking whether it's empty essentially requires doing something like std.algorithm `walkLength`, but if all you need is basic iteration, it can be a simpler solution: Yes, `opApply()` works! You just need to use `do while()` instead of `while()` because it skips the first item. ```d struct Node { int item; Node* next; } class List { Node* root, iter; this(int item = 0) { iter = new Node(item, null); root = iter; } List dup() { auto backup = new List(); backup.root = root; backup.iter = iter; return backup; } void insertFront(T)(T item) { (*iter).next = new Node(item, null); this.Next; } bool empty() const => iter is null; auto front() inout => iter; auto popFront()=> iter = this.Next; auto getItem() => iter.item; auto rewind() => iter = root; } auto Next(List list) => list.iter = list.iter.next; auto gaussian(T)(T n)=> (n * n + n) / 2; void main() { import std.stdio; enum LIMIT = 10; auto list = new List(1); foreach(t; 2 .. LIMIT + 1) { list.insertFront(t); } auto tmp = list.dup; list.rewind(); size_t sum; do sum += list.getItem; while(list.Next); assert(gaussian(LIMIT) == sum); sum.writeln; // 55 auto next = LIMIT + 1; tmp.insertFront(next); tmp.rewind(); sum = 0; foreach(t; tmp) sum += t.item; assert(gaussian(LIMIT) + next == sum); sum.writeln; // 66 tmp.rewind(); auto range = Range(tmp); foreach(r; range) r.item.write(" "); writeln; // 2 3 4 5 6 7 8 9 10 11 // ? (1) --^ } struct Range { private List iter; int opApply(scope int delegate(Node* t) dg) { while(auto current = iter.Next) { if (auto r = dg(current)) return r; } return 0; } } ``` SDB@79
Re: Inconsistent chain (implicitly converts to int)
On Saturday, 6 April 2024 at 09:21:34 UTC, rkompass wrote: I checked: ```d import std.stdio, std.range, std.algorithm; struct N(T) { T last, step, first; bool empty() => first >= last; T front() => first; auto popFront() => first += step; } void main() { auto r1 = N!size_t(10, 1, 1); auto r2 = N!real(15, .5, 10); ``` and it seems to work as I said. Thank you for checking again, but it is important to be solution oriented. How about Tuple? Yes, it might be wise to use a tuple in this case: ```d //... auto tuple = a.zip(b); tuple.writeln; // [Tuple!(int, dchar)(97, 'd'), Tuple!(int, dchar)(98, 'e'), Tuple!(int, dchar)(99, 'f')] tuple.map!(num => num[0].to!dchar).write; tuple.map!"a[1]".writeln; // abcdef } ``` SDB@79
Re: CTFE write message to console
On Friday, 5 April 2024 at 14:41:12 UTC, Carl Sturtivant wrote: On Friday, 5 April 2024 at 07:37:20 UTC, Paolo Invernizzi wrote: pragma(msg, x) ? No. `__ctfeWrite(x)` is executed inside an executing function like any other statement in it, and can have an argument `x` computed during that execution. It is defined to output the computed text `x` to stderr when the function it is a part of is called as CTFE by the compiler and to be a no-op if that function is called at run time in the compiled executable. So it is a replacement for `std.stdio.write` in a CTFE function, handy among other things for reporting what's going on during the execution of that function by the compiler. `pragma(msg, x)` works during its *compilation*, so putting it as a line in a CTFE-called function would not execute it when the function is called by the compiler. That being the case, `x` may not be a value computed when that function executes. Such a value is "not available at compile time", only at CTFE run time. The CTFE function is not running when it is being compiled. It is possible that `x` in `pragma(msg, x)` be computed with a call to a function as its return value, i.e. computed by CTFE, but that call will be made when `pragma(msg, x)` is compiled, and is a part of compiling it. Only when the function has returned producing `x` does the `pragma(msg, x)` do its work. This works: ```d alias E = double; auto r = 0.iota!E(1,.05) static this() { alias ranges = imported!"std.meta".AliasSeq!(isRandomAccessRange, isForwardRange, isInputRange, isOutputRange, isBidirectionalRange); static foreach(R; ranges) pragma(msg, R!(typeof(r), E)); } void main() {} ``` SDB@79
Re: Inconsistent chain (implicitly converts to int)
On Friday, 5 April 2024 at 21:16:42 UTC, rkompass wrote: In the first example the int's are converted to doubles (also common type). But they appear as int's because writeln does not write a trailing .0. But it doesn't work as you say! I even tried it on an older version and got the same result. SDB@79
Re: Inconsistent chain (implicitly converts to int)
On Friday, 5 April 2024 at 16:05:20 UTC, H. S. Teoh wrote: On Fri, Apr 05, 2024 at 03:18:09PM +, Salih Dincer via Digitalmars-d-learn wrote: Hi everyone, Technically r1 and r2 are different types of range. Isn't it inconsistent to chain both? If not, why is the char type converted to int? [...] It's not inconsistent if there exists a common type that both range element types implicit convert to. The real problem is the implicit conversion of char to int, which I have been against for a long time. Walter, however, disagrees. T ```d auto a = [97, 98, 99]; auto b = ['d', 'e', 'f']; a.chain(b).map!(chr => chr.to!char).writeln; // abcdef ``` Nice, there is a solution that requires memory allocation, but it still makes you think! However, they can fix this in Phobos3 because now we have this too: https://dlang.org/changelog/2.108.0.html#range_predicate_element PS. I think I unintentionally made a chain by repeating the source code above, sorry :) SDB@79
Inconsistent chain (implicitly converts to int)
Hi everyone, Technically r1 and r2 are different types of range. Isn't it inconsistent to chain both? If not, why is the char type converted to int? ```d import std.stdio, std.range; void main() { auto r1 = N!size_t(10, 1, 1); auto r2 = N!real(15, .5, 10); r1.chain(r2).writeln; // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5] auto a = [97, 98, 99]; auto b = ['d', 'e', 'f']; a.chain(b).writeln; // [97, 98, 99, 100, 101, 102] } struct N(T) { T last, step, first; bool empty() => first >= last; T front() => first; auto popFront() => first += step; } void main() { auto r1 = N!size_t(10, 1, 1); auto r2 = N!real(15, .5, 10); r1.chain(r2).writeln; // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5] auto a = [97, 98, 99]; auto b = ['d', 'e', 'f']; a.chain(b).writeln; // [97, 98, 99, 100, 101, 102] } struct N(T) { T last, step, first; bool empty() => first >= last; T front() => first; auto popFront() => first += step; } ``` SDB@79
Re: How to add a character literal to a string without ~ operator?
On Thursday, 4 April 2024 at 19:56:50 UTC, Ferhat Kurtulmuş wrote: My favorite d feature is lazy ranges. No allocation here. ```d auto s = chain("as ", "df ", "j"); // s is lazy writeln(s); ``` ```d import std.range : chain; void main() { string word = "hello"; auto noError = chain(word, "f", " ", "World"); /** auto noCompile = chain('f', " ", "World"); * ^ *|/ } ``` SDB@79
Re: How to add a character literal to a string without ~ operator?
On Thursday, 4 April 2024 at 18:14:54 UTC, BoQsc wrote: I'm looking for more readable standard function to add a **character** literal to a **string**. The `~` operator is clearly not great while reading a source code. I'm not here to discuss that. I'm looking for a function inside standard library. The function should be straightforward, up to two words. Here is what I expect from a programming language: Pseudo example: ```d import std.array, std.stdio; void main() { auto word = appender("hello"); word.put('f'); word.put(" "); word.put("World"); word.writeln; } ``` SDB@79
Re: CTFE write message to console
On Thursday, 4 April 2024 at 15:47:53 UTC, Richard (Rikki) Andrew Cattermole wrote: Oh hey! https://github.com/dlang/dmd/pull/16250 It was implemented literally 2 weeks ago! Nightly should have it https://github.com/dlang/dmd/releases/tag/nightly Good news, thanks... SDB@79
Re: Setting up a final switch from a list
On Friday, 29 March 2024 at 00:37:21 UTC, Jonathan M Davis wrote: On Thursday, March 28, 2024 4:21:03 PM MDT Salih Dincer via Digitalmars-d- learn wrote: How can we add all members of an enum type to a list without duplicating code? As the documentation for EnumMembers explains, you can use std.meta.NoDuplicates to strip out duplicates if you want to do something like generate a switch statement from the list of enum members. https://dlang.org/phobos/std_traits.html#EnumMembers - Jonathan M Davis I guess this falls into metaprogramming. Maybe we should expect this possibility from IDEs because I've seen something like this in VScode. All enum members were added automatically. SDB@79
Re: Why is this code slow?
On Friday, 29 March 2024 at 00:04:14 UTC, Serg Gini wrote: On Thursday, 28 March 2024 at 23:15:26 UTC, Salih Dincer wrote: There is no such thing as parallel programming in D anyway. At least it has modules, but I didn't see it being works. Whenever I use toys built in foreach() it always ends in disappointment I think it just works :) Which issues did you have with it? A year has passed and I have tried almost everything! Either it went into an infinite loop or nothing changed at the speed. At least things are not as simple as openMP on the D side! First I tried this code snippet: futile attempt! ```d struct RowlandSequence { import std.numeric : gcd; import std.format : format; import std.conv : text; long b, r, a = 3; enum empty = false; string[] front() { string result = format("%s, %s", b, r); return [text(a), result]; } void popFront() { long result = 1; while(result == 1) { result = gcd(r++, b); b += result; } a = result; } } enum BP { f = 1, b = 7, r = 2, a = 1, /* f = 109, b = 186837516, r = 62279173, //*/ s = 5 } void main() { RowlandSequence rs; long start, skip; with(BP) { rs = RowlandSequence(b, r); start = f; skip = s; } rs.popFront(); import std.stdio, std.parallelism; import std.range : take; auto rsFirst128 = rs.take(128); foreach(r; rsFirst128.parallel) { if(r[0].length > skip) { start.writeln(": ", r); } start++; } } ``` SDB@79
Re: Two chunks but No allocation
On Thursday, 28 March 2024 at 23:08:54 UTC, rkompass wrote: You can drop and take from the folded values range. I got `[1, 0.67, 0.625, 0.619048, 0.618182, 0.618056, 0.618037, 0.618034, 0.618034, 0.618034]` from the above code. Thank you so much... I solved the problem: r.back doesn't work because recurrence() runs forever and you need to use it with take. In other words, the range functions up to the map must have members such as length() and opSlice(). SDB@79
Re: range.chunks(2) error
On Thursday, 28 March 2024 at 17:50:17 UTC, Salih Dincer wrote: Hi, When I use the chunks() template with iota(), for instance, with chunks(2), I can access both r.front and r.back. However, in a range of my own type (named iras in the code below), only r.front is working. I think the error given by r.back is not a bug related to chunks, is it? It's really nice to solve a problem on your own. Turns out I needed to add save, opSlice, length and opDollar members to the range. SDB@79
Re: Why is this code slow?
On Thursday, 28 March 2024 at 20:18:10 UTC, rkompass wrote: I didn't know that OpenMP programming could be that easy. Binary size is 16K, same order of magnitude, although somewhat less. D advantage is gone here, I would say. There is no such thing as parallel programming in D anyway. At least it has modules, but I didn't see it being works. Whenever I use toys built in foreach() it always ends in disappointment :) SDB@79
Re: Setting up a final switch from a list
On Thursday, 10 August 2023 at 08:33:13 UTC, Christian Köstlin wrote: I think one part of the original question (now fanished in the nntp backup) was how to get all enum members into a list without duplicating code. ```d import std.traits : EnumMembers; import std.stdio : writeln; import std.algorithm : map; import std.conv : to; enum alphabet { a, b, c, d } void main() { writeln(EnumMembers!alphabet); writeln([EnumMembers!alphabet]); writeln([EnumMembers!alphabet].map!(a => "test" ~a.to!string)); } ``` results in ```d abcd [a, b, c, d] ["testa", "testb", "testc", "testd"]``` ``` How can we add all members of an enum type to a list without duplicating code? I wonder if this is something we'll see soon as the D language feature? In the D programming language, this can be achieved using features provided by the language such as __traits and AliasSeq. For instance, the EnumMembers trait from the std.traits module returns all members of an enum type as a tuple. This tuple contains the enum members in sequence, allowing for iteration over them or conversion into a list. Finally, utilizing these language features to avoid code duplication and write cleaner, more maintainable code is a good practice. Sorry to resurrect this old thread, but what do you think; people living in 2024 ? SDB@79
range.chunks(2) error
Hi, When I use the chunks() template with iota(), for instance, with chunks(2), I can access both r.front and r.back. However, in a range of my own type (named iras in the code below), only r.front is working. I think the error given by r.back is not a bug related to chunks, is it? ```d import std.array, std.algorithm, std.range, std.stdio; void main() { auto rng1 = iota!real(24.0, 1321.0, 16.5).take(8); auto rng2 = iras!real(24.0, 1321.0, 16.5).take(8); auto noError = rng1.chunks(2) .map!(r => r.back - r.front); assert(noError.equal([16.5, 16.5, 16.5, 16.5])); /* auto error = rng2.chunks(2) .map!(r => r.back - r.front);/* main.d(18): Error: none of the overloads of template `std.range.primitives.back` are callable using argument types `!()(Take!(InclusiveRange))`*/ } /* * iras v3 * (inclusiveRange) Source: * https://forum.dlang.org/post/bnnxentwstkjnxkyc...@forum.dlang.org */ ``` The same problem occurs here: ```d struct Range(T) { T n = 3; bool empty; alias back = front; auto front() => n.cube - n * 0.5; auto popFront() => n += 2; auto backFront() => n -= 2; } ``` SDB@79
Re: Why is this code slow?
On Thursday, 28 March 2024 at 11:50:38 UTC, rkompass wrote: Turning back to this: Are there similarly simple libraries for C, that allow for parallel computation? You can achieve parallelism in C using libraries such as OpenMP, which provides a set of compiler directives and runtime library routines for parallel programming. Here’s an example of how you might modify the code to use OpenMP for parallel processing: ```c #include #include #include #define ITERS 10 #define STEPS 31 double leibniz(int i) { double r = (i == ITERS) ? 0.5 * ((i % 2) ? -1.0 : 1.0) / (i * 2.0 + 1.0) : 0.0; for (--i; i >= 0; i -= STEPS) r += ((i % 2) ? -1.0 : 1.0) / (i * 2.0 + 1.0); return r * 4.0; } int main() { double start_time = omp_get_wtime(); double result = 0.0; #pragma omp parallel for reduction(+:result) for (int s = ITERS; s >= 0; s -= STEPS) { result += leibniz(s); } // Calculate the time taken double time_taken = omp_get_wtime() - start_time; printf("%.16f\n", result); printf("%f (seconds)\n", time_taken); return 0; } ``` To compile this code with OpenMP support, you would use a command like gcc -fopenmp your_program.c. This tells the GCC compiler to enable OpenMP directives. The #pragma omp parallel for directive tells the compiler to parallelize the loop, and the reduction clause is used to safely accumulate the result variable across multiple threads. SDB@79
Re: Two chunks but No allocation
On Wednesday, 27 March 2024 at 20:50:05 UTC, rkompass wrote: This works: I decided to give the full code. Maybe then it will be better understood what I mean. I actually pointed out the indirect solution above but it's a bit ugly and I'm sure there must be a better way? ```d import std.datetime.stopwatch; import std.stdio, std.algorithm, std.range; auto cube(T)(T n) => n * n * n; auto S1(T, R)(R a, T n) => n.cube - n; // auto s1(T)(T first, size_t skip = 3) => recurrence!S1(0, first).drop(skip); enum ITERATIONS = 14_000; enum BENCHMARKS = 100; void main() { real result; long total_time = 0; for(int i = 0; i < BENCHMARKS; i++) { auto sw = StopWatch(AutoStart.no); sw.start(); result = s1(3.0).take(ITERATIONS) .chunks(2) .map!(r => 4/r.front) .array // <- can't it be done without this? .chunks(2) .map!"a[0] - a[1]" .fold!"a + b"(3.0); sw.stop(); total_time += sw.peek.total!"nsecs"; } writefln("%f (nsecs)", total_time / BENCHMARKS / 1e9); writefln("%0.16f (result)", result);``` } /* 0.000456 (nsecs) 3.1415926535890670 (result) //*/ ``` SDB@79
Re: Why is this code slow?
On Wednesday, 27 March 2024 at 08:22:42 UTC, rkompass wrote: I apologize for digressing a little bit further - just to share insights to other learners. Good thing you're digressing; I am 45 years old and I still cannot say that I am finished as a student! For me this is version 4 and it looks like we don't need a 3rd variable other than the function parameter and return value: ```d auto leibniz_v4(int i) @nogc pure { double n = 0.5*((i%2) ? -1.0 : 1.0) / (i * 2.0 + 1.0); while(--i >= 0) n += ((i%2) ? -1.0 : 1.0) / (i * 2.0 + 1.0); return n * 4.0; } /* 3.1415926535892931 3.141592653589 793238462643383279502884197169399375105 3.14159365359077420 (v1) Avg execution time: 0.33 */ ``` SDB@79
Two chunks but No allocation
Is it possible to process both chunks without requiring memory allocation (not using an array)? For example: ```d import std; void main() { auto fib = (real a, real b) => recurrence!"a[n-1] + a[n-2]"(a, b); auto myFib = fib(1, 1).take(48).array; auto goldenRadio = myFib.chunks(2).map! //"a[1] / a[0]";/* line #9 ((a) { const m = a.front; a.popFront(); const n = a.front; return m/n; });//*/ goldenRadio.back.writefln!"%.21f"; writeln("0.61803398874989484820"); } ``` Of course, it also works if you remove the comment marks on line #9 but I'm still using .array because the .chunks error tells me that. So, not works this: ```d fib(1, 1).take(48) //.array .chunks(2) .map!"a[1] / a[0]" .back .writeln; // 1.61803 ``` Thanks... SDB@79
Re: Why is this code slow?
On Monday, 25 March 2024 at 14:02:08 UTC, rkompass wrote: Of course you may also combine the up(+) and down(-) step to one: 1/i - 1/(i+2) = 2/(i*(i+2)) ```d double leibniz(int iter) { double n = 0.0; for (int i = 1; i < iter; i+=4) n += 2.0 / (i * (i+2.0)); return n * 4.0; } ``` or even combine both approaches. But of, course mathematically much more is possible. This was not about approximating pi as fast as possible... The above first approach still works with the original speed, only makes the result a little bit nicer. It's obvious that you are a good mathematician. You used sequence A005563. First of all, I must apologize to the questioner for digressing from the topic. But I saw that there is a calculation difference between real and double. My goal was to see if there would be a change in speed. For example, with 250 million cycles (iter/4) I got the following result: 3.14159265158976691 (250 5million (with real) 3.14159264457621568 (250 million with double) 3.14159265358979324 (std.math.constants.PI) First of all, my question is: Why do we see this calculation error with double? Could the changes I made to the algorithm have caused this? Here's an executable code snippet: ```d enum step = 4; enum loop = 250_000_000; auto leibniz(T)(int iter) { T n = 2/3.0; for(int i = 5; i < iter; i += step) { T a = (2.0 + i) * i; // https://oeis.org/A005563 n += 2/a; } return n * step; } import std.stdio : writefln; void main() { enum iter = loop * step-10; 65358979323.writefln!"Compare.%s"; iter.leibniz!double.writefln!"%.17f (double)"; iter.leibniz!real.writefln!"%.17f (real)"; imported!"std.math".PI.writefln!"%.17f (enum)"; } /* Prints: Compare.65358979323 3.14159264457621568 (double) 3.14159265158976689 (real) 3.14159265358979324 (enum) */ ``` In fact, there are algorithms that calculate accurately up to 12 decimal places with fewer cycles. (e.g. ) SDB@79
Re: Why is this code slow?
On Sunday, 24 March 2024 at 22:16:06 UTC, Kdevel wrote: The term containing the `pow` invocation computes the alternating sequence -1, 1, -1, ..., which can be replaced by e.g. ```d immutable int [2] sign = [-1, 1]; n += sign [i & 1] / (i * 2.0 - 1.0); ``` This saves the expensive call to the pow function. I also used this code: ```d import std.stdio : writefln; import std.datetime.stopwatch; enum ITERATIONS = 1_000_000; enum BENCHMARKS = 20; auto leibniz(bool speed = true)(int iter) { double n = 1.0; static if(speed) const sign = [-1, 1]; for(int i = 2; i < iter; i++) { static if(speed) { const m = i << 1; n += sign [i & 1] / (m - 1.0); } else { n += pow(-1, i - 1) / (i * 2.0 - 1.0); } } return n * 4.0; } auto pow(F, G)(F x, G n) @nogc @trusted pure nothrow { import std.traits : Unsigned, Unqual; real p = 1.0, v = void; Unsigned!(Unqual!G) m = n; if(n < 0) { if(n == -1) return 1 / x; m = cast(typeof(m))(0 - n); v = p / x; } else { switch(n) { case 0: return 1.0; case 1: return x; case 2: return x * x; default: } v = x; } while(true) { if(m & 1) p *= v; m >>= 1; if(!m) break; v *= v; } return p; } void main() { double result; long total_time = 0; for(int i = 0; i < BENCHMARKS; i++) { auto sw = StopWatch(AutoStart.no); sw.start(); result = ITERATIONS.leibniz;//!false; sw.stop(); total_time += sw.peek.total!"nsecs"; } result.writefln!"%0.21f"; writefln("Avg execution time: %f\n", total_time / BENCHMARKS / 1e9); } ``` and results: dmd -run "leibnizTest.d" 3.141594653593692054727 Avg execution time: 0.002005 If I compile with leibniz!false(ITERATIONS) the average execution time increases slightly: Avg execution time: 0.044435 However, if you pay attention, it is not connected to an external library and a power function that works with integers is used. Normally the following function of the library should be called: Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @nogc @trusted pure nothrow if (isFloatingPoint!(F) && isFloatingPoint!(G)) ... Now, the person asking the question will ask why it is slow even though we use exactly the same codes in C; rightly. You may think that the more watermelon you carry in your arms, the slower you naturally become. I think the important thing is not to drop the watermelons :) SDB@79
Re: Challenge: Make a data type for holding one of 8 directions allowing increment and overflow
On Wednesday, 13 March 2024 at 10:27:49 UTC, Basile B. wrote: The semantics of the operators are actually not as clear as that. What if you define ```d enum Direction { N = 1, NE, S = 45, SW } ``` ? Certainly! EnumMembers; can be used. The EnumMembers template from the std.traits module is used to retrieve all the members of an enumeration. It generates a tuple containing all the enumeration values, which can be iterated over using a foreach loop. In the D programming language, you can use EnumMembers to iterate over enum values at compile time, which is useful for generating code based on enum members. Here’s a simple code example: ```d enum Days { Monday= 1001, Tuesday = 1010, Wednesday = 1011, Thursday = 1100, Friday= 1101, Saturday = 1110, Sunday= } import std.traits : EnumMembers; foreach(day; EnumMembers!Days) day.writeln(":", cast(int)day); ``` SDB@79
Re: Challenge: Make a data type for holding one of 8 directions allowing increment and overflow
On Tuesday, 12 March 2024 at 05:38:03 UTC, Liam McGillivray wrote: Perhaps this would be a good programming challenge for someone more experienced than me. Make a data type (probably a struct) for holding one of 8 directional values using 3 bits. It should accept the use of increment operators to change the angle. D is such a perfect language that you can do the features you mentioned and more. I also implemented the following during my rookie years: ```d alias Direction = enumSet; union enumSet(T) { T e; alias e this; struct { int i; auto opUnary(string op: "++")() => i = i < e.max ? ++i : e.min; auto opUnary(string op: "--")() => i = i > e.min ? --i : e.max; auto opOpAssign(string op: "+")(int val) { i += val; if(i > e.max) i -= e.max + 1; } auto opOpAssign(string op: "-")(int val) { i -= val; if(i < e.min) i += e.max + 1; } } string toString() const => e.to!string; } unittest { auto direction = Direction!Directions(Directions.N); direction++; assert(direction == Directions.NE); direction+=3; assert(direction == Directions.S); direction--; assert(direction == Directions.SE); direction-=4; assert(direction == Directions.NW); } import std.stdio, std.conv; void main() { enum Directions { N , NE , E, SE, S, SW , W, NW } auto test = enumSet!Directions(Directions.W); test += 9; /* ++test; ++test; ++test; ++test; ++test; ++test; ++test; ++test; ++test;//*/ test.writeln; test--; test--; test.writeln; } ``` Here union was used with an extra template parameter. I also added 2 aliases to avoid confusion. SDB@79
Re: struct initializer
Hi All, I feel lonely, just as those who come from C++ find it strange, because I think it makes it difficult to read code. On Friday, 1 December 2023 at 14:53:16 UTC, Paul Backus wrote: Technically you don't *have* to repeat the type. You can write the return type as `auto`: ```d auto fun() { return S(5, 2); } ``` Or you can use `typeof(return)`: ```d SomeReallyLongReturnType fun() { return typeof(return)(5, 2); } ``` Paul's example is very readable and short so it's nice. Moreover, when there are named parameters in D, what is the need for them. While there is so much convenience in D, getting stuck on a very simple option... You decide: ```d struct Point { int x, y; auto opBinary(string op : "-")(Point that) => Point(this.x - that.x, this.y - that.y); auto opBinary(string op : "+")(Point that) => Point(this.x + that.x, this.y + that.y); auto opBinary(string op : "*")(Point that) => Point(this.x * that.x, this.y * that.y); // Moreover, it was possible to do this trio // at once with mixin... } void main() { auto upperRightCorner = Point(y:768); Point x = { 10, 268 }; import std.stdio : dout = writeln; dout(upperRightCorner - x); dots(a: upperRightCorner, b: x).dout; } alias dots = differenceOfTwoSquares; auto differenceOfTwoSquares(Point a, Point b) => (a - b)*(a + b); /* * dmd -run "namedParameters.d" * Point(-10, 500) * Point(-100, 518000) */ ``` SDB@79
Re: Convert String to Date and Add ±N Hours
On Saturday, 4 November 2023 at 21:10:38 UTC, Steven Schveighoffer wrote: On Saturday, 4 November 2023 at 18:11:53 UTC, Vahid wrote: Hi, I have a date string with the format of "2023-11-04 23:10:20". I want to convert this string to Date object and also, add ±N hours to it. For example: `"2023-11-04 23:10:20" + "+2:00" = "2023-11-05 01:10:20"` `"2023-11-04 23:10:20" + "-2:30" = "2023-11-05 20:40:20"` How can I do this? Parse the date. There is a nice package on code.dlang.org that is for date parsing: https://code.dlang.org/packages/dateparser -Steve I couldn't get it to work, can you help me with this? I think the error is related to line 803 in the package.d file: import containers.dynamicarray : DynamicArray; This means it is dependent on containers by Dlang Community. This was installed it: https://github.com/dlang-community/containers However I get these errors: dmd -w -of"bench.a" "bench.d" containers/package.d dateparser/package.d /usr/bin/ld: bench.o:(.data.rel.ro+0x60): undefined reference to `_D10containers12dynamicarray12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x78): undefined reference to `_D10containers8internal4node12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x120): undefined reference to `_D10containers12cyclicbuffer12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x128): undefined reference to `_D10containers12dynamicarray12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x130): undefined reference to `_D10containers7hashmap12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x138): undefined reference to `_D10containers7hashset12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x140): undefined reference to `_D10containers11openhashset12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x148): undefined reference to `_D10containers5slist12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x150): undefined reference to `_D10containers7treemap12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x158): undefined reference to `_D10containers5ttree12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x160): undefined reference to `_D10containers12unrolledlist12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x1c8): undefined reference to `_D10dateparser9timelexer12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x1d0): undefined reference to `_D10dateparser3ymd12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x1d8): undefined reference to `_D10dateparser11parseresult12__ModuleInfoZ' /usr/bin/ld: bench.o:(.data.rel.ro+0x1e0): undefined reference to `_D10dateparser10parserinfo12__ModuleInfoZ' /usr/bin/ld: bench.o: in function `_Dmain': dateparser/package.d:(.text._Dmain[_Dmain]+0x1e): undefined reference to `_D10dateparser10parserinfo10ParserInfo7__ClassZ' /usr/bin/ld: dateparser/package.d:(.text._Dmain[_Dmain]+0x2f): undefined reference to `_D10dateparser10parserinfo10ParserInfo6__ctorMFNfbbZCQBzQBqQBh' /usr/bin/ld: bench.o: in function `_D3std4conv__T6toImplTEQv8datetime4date5MonthTSQBt8typecons__T8NullableTiViN2147483648ZQzZQCyFQBwZQCy': dateparser/package.d: . . . collect2: error: ld returned 1 exit status Error: linker exited with status 1 SDB@79
Re: bigEndian in std.bitmanip
On Tuesday, 31 October 2023 at 14:43:43 UTC, Imperatorn wrote: It might make sense to change since little endian is the most common when it comes to hardware. But big endian is most common when it comes to networking. So I guess it depends on your view of what is most common. Interacting with your local hardware or networking. I realized that I had to make my prefer based on the most common. But I have to use Union. That's why I have to choose little.Endian. Because it is compatible with both Union and HexString. My test code works perfectly as seen below. I'm grateful to everyone who helped here and [on the other thread](https://forum.dlang.org/thread/ekpvajiablcfueyip...@forum.dlang.org). ```d enum sampleText = "Hello D!"; // length <= 8 char void main() { //import sdb.string : UnionBytes; mixin UnionBytes!size_t; bytes.init = sampleText; import std.digest: toHexString; auto hexF = bytes.cell.toHexString; assert(hexF == "48656C6C6F204421"); import std.string : format; auto helloD = sampleText.format!"%(%02X%)"; assert(hexF == helloD); import std.stdio; bytes.code.writeln(": ", helloD); /* Prints: 2397076564600448328: 48656C6C6F204421 */ import std.conv : hexString; static assert(sampleText == hexString!"48656C6C6F204421"); //import sdb.string : readBytes; auto code = bytes.cell.readBytes!size_t; assert(code == bytes.code); bytes.init = code; code.writeln(": ", bytes); /* Prints: 2397076564600448328: Hello D! */ assert(bytes[] == [72, 101, 108, 108, 111, 32, 68, 33]); //import sdb.string : HexString auto str = "0x"; auto hex = HexString!size_t(bytes.code); hex.each!(chr => str ~= chr); str.writeln; // 0x48656C6C6F204421 } ``` My core template (UnionBytes) is initialized like this, and underneath I have the readBytes template, which also works with static arrays: ```d // ... import std.range : front, popFront; size_t i; do // new version: range support { char chr; // default init: 0xFF chr &= str.front; // masking code |= T(chr) << (i * 8); // shifting str.popFront; // next char } while(++i < size); } auto opCast(Cast : T)() const => code; auto opCast(Cast : string)() const => this.format!"%s"; auto toString(void delegate(in char[]) sink) const => sink.formattedWrite("%s", cast(char[])cell); } UnionBytes bytes; // for mixin } template readBytes(T, bool big = false, R) {// pair endian version 2.1 import std.bitmanip; static if(big) enum E = Endian.bigEndian; else enum E = Endian.littleEndian; import std.range : ElementType; alias ET = ElementType!R; auto readBytes(ref R dat) { auto data = cast(ET[])dat; return read!(T, E)(data); } } ``` SDB@79
Re: Function Overloading
On Wednesday, 1 November 2023 at 20:04:52 UTC, Basile B. wrote: Yes. D constructors are not named but the current implementation adds a name that is `__ctor`, so add ```d alias add = __ctor; ``` to you struct. Yeah, it works! Thanks...:) SDB@79
Function Overloading
```d struct Calculate { int memory; string result; auto toString() => result; this(string str) { add(str); } this(int num) { add(num); } import std.string : format; void add(string str) { result ~= str.format!"%s + "; } void add(int num) { memory += num; add(num.format!"%s"); } } import std.stdio; void main() { // without constructor: Calculate c; c.add("x"); c.add(2); c.writeln; // x + 2 + // with constructor: c = Calculate("x"); c.add(2); c.writeln; // x + 2 + } ``` There is a simple struct like the one above that is not related to reality. There can be more than 2 function overloading in it, but in our example there are only 2. Without implementing a similar function again for each constructor; is it possible to do something like `alias add = this;`? ```d struct Calculate { int memory; string result; auto toString() => result; // alias add = this; import std.string : format; this(string str) { result ~= str.format!"%s + "; } this(int num) { memory += num; add(num.format!"%s"); } } ``` SDB@79
Re: bigEndian in std.bitmanip
On Tuesday, 31 October 2023 at 10:24:56 UTC, Jonathan M Davis wrote: On Tuesday, October 31, 2023 4:09:53 AM MDT Salih Dincer via Digitalmars-d- learn wrote: Hello, Why isn't Endian.littleEndian the default setting for read() in std.bitmanip? Why would you expect little endian to be the default? The typical thing to do when encoding integral values in a platform-agnostic manner is to use big endian, not little endian... Because when we create a structure with a Union, it does reverse insertion with according to the static array(bytes) index; I showed this above. I also have a convenience template like this: ```d template readBytes(T, bool big = false, R) {// pair endian version 2.0 import bop = std.bitmanip; static if(big) enum E = bop.Endian.bigEndian; else enum E = bop.Endian.littleEndian; auto readBytes(ref R dat) => bop.read!(T, E)(dat); } ``` Sorry to give you extra engage because I already solved the problem with readBytes(). Thank you for your answer, but there is 1 more problem, or even 2! The read() in the library, which is 2nd function, conflicts with std.write. Yeah, there are many solutions to this, but what it does is just read bytes. However, you can insert 4 ushorts into one ulong. Don't you think the name of the function should be readBytes, not read? Because it doesn't work with any type other than ubyte[]! SDB@79
bigEndian in std.bitmanip
Hello, Why isn't Endian.littleEndian the default setting for read() in std.bitmanip? Okay, we can easily change this if we want (I could use enum LE in the example) and I can also be reversed with data.retro.array(). ```d void main() { import std.conv : hexString; string helloD = hexString!"48656C6C6F204421"; // compile time converted literal string -ˆ import std.string : format; auto hexF = helloD.format!"%(%02X%)"; import std.digest: toHexString; auto arr = cast(ubyte[])"Hello D!"; auto hex = arr.toHexString; assert(hex == hexF); import std.stdio : writeln; hex.writeln(": ", helloD); // 48656C6C6F204421: Hello D! assert(helloD == "Hello D!"); auto data = arr.readBytes!size_t; data.code.writeln(": ", data.bytes); // 2397076564600448328: Hello D! } template readBytes(T, R) { union Bytes { T code; char[T.sizeof] bytes; } import std.bitmanip; enum LE = Endian.littleEndian; auto readBytes(ref R data) { import std.range : retro, array; auto reverse = data.retro.array; return Bytes(reverse.read!T); } } ``` However, I think it is not compatible with Union. Thanks... SDB@79
Re: SlicedString Length
Good news! I collected them in a template with the condition of running split() once at compile time. The result seems perfect? What are your thoughts? ```d void main() { auto slc = sliceOff!"abc def ghi"; auto len = slc.length; slc.index = len; import std.stdio, std.algorithm: equal; assert(slc.equal(["abc", "def", "ghi"])); foreach(s; slc) s.write; writeln; // abcdefghi // Push Test with(slc) { string test = "jkl"; push(test); auto p = elementsPos[$ - 1]; assert(data[p[0]..p[1]] == test); } foreach(s; slc) s.write; writeln; // abcdefghijkl auto tmp = slc.dup; assert(tmp.front == "abc"); tmp.popFront; assert(slc.front == "abc"); assert(tmp.front == "def"); } template sliceOff(string STR, string SEP = " ") { auto sliceOff() { SlicedString s; s.popFront(); return s; } import std.array : split; import std.range : walkLength; enum LEN = STR.split(SEP).walkLength; struct SlicedString { long index, back, next = -1; size_t len = LEN; string data = STR; auto push(string data) { this.data ~= SEP ~ data; len++; index++; } auto elementsPos() { long[][] result; auto r = this.dup; while(!r.empty) { result ~= [r.back, r.next]; r.popFront(); } return result; } alias dup = save; auto save() { return this; } auto length() { return len; } bool empty() { return index == 0; } auto front() { return data[back..next]; } void popFront() { import std.string : find = indexOf; --index; back = ++next; next = data.find(SEP, next); if(next == -1) { next = data.length; } } } } ``` SDB@79
SlicedString Length
Hi, I have a string wrapper called SlicedString. What it does is very simple: Returning each piece as a slice with a assured separator at compile time by used indexOf() ! Here it is: ```d struct SlicedString(string E) { long index, back, next = -1; string data; auto length() const { import std.array : split; import std.range : walkLength; return data.split(E).walkLength; } auto popIndex(ref SlicedString!E range) { scope(exit) range.popFront(); return [range.back, range.next]; } auto elementsPos() { long[][] result; auto r = SlicedString!E(index, back, next, data); while(!r.empty) { result ~= popIndex(r); } return result; } bool empty() { return index == 0; } auto front() { return data[back..next]; } void popFront() { import std.string : find = indexOf; --index; back = ++next; next = data.find(E, next); if(next == -1) { next = data.length; } } } auto sliceOff(string E = " ")(string data) { SlicedString!E s; s.data = data; s.popFront(); return s; } // UNIT TESTS: void main() { auto str = "abc def ghi"; auto slc = str.sliceOff; auto len = slc.length; slc.index = len; import std.stdio, std.algorithm: equal; assert(slc.equal(["abc", "def", "ghi"])); // Print range: foreach(s; slc) s.write; writeln; // Print Elements Position slc.elementsPos.writeln; slc.elementsPos.writeln; } ``` The unit tests work as I want, but I find calculating the length with split() too expensive; despite walkLength()... Is there a more accurate method? Last year, Ali Çehreli told me that splitter() was also possible, but then he did something with map(). I really don't understand these! Thanks... SDB@79
Re: How to use ".stringof" to get the value of a variable and not the name of the variable (identifier) itself?
On Sunday, 15 October 2023 at 07:22:53 UTC, Imperatorn wrote: You already got a lot of good answers, I thought I'd just share this for anyone searching for nogc string formatting compatible with betterC: https://code.dlang.org/packages/bc-string Doesn't it make more sense to use [ParseResult!T parse(T)(cstring str)](https://github.com/tchaloupka/bc-string/blob/master/source/bc/string/conv.d) instead of nested if's here: https://github.com/tchaloupka/bc-string/blob/master/source/bc/string/numeric.d Thanks, SDB@79
Re: How to use ".stringof" to get the value of a variable and not the name of the variable (identifier) itself?
On Monday, 9 October 2023 at 16:33:32 UTC, rempas wrote: I'm trying to create a series of function. There will be ten of them, and they will be called `function_0`, `function_1`, etc. However, in my example, "stringof" returns the character "i" itself and turns that into a string instead of getting its actual value (number). Any ideas how I can achieve what I'm trying to achieve? Great masters generally warn to stay away from stringof. Please do not use it as much as possible. The following code snippet will be useful to you: ```d alias CN = __traits(allMembers, CardinalNumbers); static foreach(i; CN) { mixin(create_fn!(i[1])); } enum create_fn(char num) = ` auto function_`~ num ~`() => "Hello from function `~ num ~`!"; `; enum CardinalNumbers { n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 } void main() { assert(function_9() == "Hello from function 9!"); } ``` SDB@79
Re: Type constraint
On Tuesday, 3 October 2023 at 14:35:31 UTC, Joel wrote: Oh, I found, ```d static if (isIntegral!T) ``` seems to work. If you are using a struct, another way to affect the whole is as follows: ```d struct S(T) { invariant() { static assert(isIntegral!T); } auto addUp() { /**/ } } ``` For detailed information and examples, please continue here: https://tour.dlang.org/tour/en/gems/contract-programming SDB@79
Re: Type constraint
On Sunday, 8 October 2023 at 10:09:02 UTC, IchorDev wrote: On Wednesday, 4 October 2023 at 01:46:42 UTC, Joel wrote: I think the if without static is still static, since it's part of the function name part, or so (outside of the curly bracket scope). You can't have regular if-statements inside templates. Regular if-statements are checked at runtime but templates only exist at compile-time. The way to write a *template constraint*—which is what you want, and uses the `if` keyword—is thus: ```d struct List(T) if(__traits(isIntegral, T)){ auto addUp() //(Add numbers) } } ``` Notice that the curly brace for the template comes after the template constraint, and that there are only 2 curly braces rather than the 3 from your example. This snippet does not compile. The curly brackets must be an even number, that is, they must terminate each other. SDB@79
Re: how to assign multiple variables at once by unpacking array?
On Monday, 9 October 2023 at 01:15:21 UTC, Salih Dincer wrote: the staticMapN() template implemented by Ali Çehreli, which is not in the standard library, is needed: It would be great if the unlimited version was added to std.meta. This template seeded/sprouted in here: https://forum.dlang.org/thread/vwxilrqgjqtvjrnjj...@forum.dlang.org SDB@79
Re: how to assign multiple variables at once by unpacking array?
On Saturday, 7 October 2023 at 16:12:47 UTC, mw wrote: Interesting: in terms of easy of coding, clarity and future maintenance, which one is superior? The one liner in Python, or your "solution" with dozen lines of code? BTW, is that a solution at all? Did it achieved what the original goal asked in the OP question? So, who should learn from whom? If you don't expect to do a single line of coding, there are many methods in D that can do this kind of thing (but at compile time). **Your snippet with struct and tupple:** ```d import std; struct MyVariables { int age, phone, country; } void main() { enum sep = ", "; enum str = "21, 3149474, 90"; enum arr = str.split(sep) .map!(x => x.to!int) .array//*/ ; alias MrSmith = AliasSeq!(arr[0], arr[1], arr[2]); auto mv = MyVariables(MrSmith); assert(mv == MyVariables(21, 3149474, 90)); } ``` and **worksheet example:** ```d import std; struct DATA(string str, T, size_t s) { enum title = str; T[s] data; } void main() { alias Columns = AliasSeq!("Stock Name", "PN Codes", "P.Prices"); alias T = AliasSeq!(string, int, double); alias Items = AliasSeq!(4, 8, 8); staticMapN!(3, DATA, Columns, T, Items) worksheet; // inputs first column: worksheet[0].data = ["capacitor", "transistor", "resistor", "varistor"]; // prints column titles: foreach(s; worksheet) s.title.writef!"%14s"; "=".repeat(42).writefln!"\n%-(%s%)"; // prints first column: foreach(name; worksheet[0].data) name.writefln!"%14s"; //... "=".repeat(42).writefln!"%-(%s%)"; }/* Prints: Stock Name PN Codes P.Prices == capacitor transistor resistor varistor == */ ``` By the way, in order for the above code snippet to work, the staticMapN() template implemented by Ali Çehreli, which is not in the standard library, is needed: ```d template staticMapN(size_t N, alias fun, args...) if(args.length % N == 0) { alias staticMapN = AliasSeq!(); static foreach (i; 0..args.length / N) { static if (N == 1) { staticMapN = AliasSeq!(staticMapN, fun!( args[i] ));} else static if (N == 2) { staticMapN = AliasSeq!(staticMapN, fun!( args[0..$ / N][i], args[$ / N..($ / N) * 2][i] ));} else static if (N == 3) { staticMapN = AliasSeq!(staticMapN, fun!( args[0..$ / N][i], args[$ / N..($ / N) * 2][i], args[($ / N) * 2..($ / N) * 3][i] ));} } } ``` SDB@79
Re: how to assign multiple variables at once by unpacking array?
On Saturday, 7 October 2023 at 07:31:45 UTC, mw wrote: https://stackoverflow.com/questions/47046850/is-there-any-way-to-assign-multiple-variable-at-once-with-dlang How to do this Python code in D: ``` s = "1 2 3" A,B,C = map(int, s.split(" ")) A,B,C (1, 2, 3) ``` Is there a better way (since 2017)? My words to those who come from Python: If you are making money from Python, please stay there, but if you want to learn new things and a modern language, "Welcome to D" and please use Tuples :) ```d import std.typecons, std.stdio; struct DICT(C, F, S) { S[C] dict; C[F] freq; void opAssign(Tuple!(C, F, S) chr) { dict[chr[0]] = chr[2]; freq[chr[1]] = chr[0]; } string toString() const { import std.array : appender; import std.algorithm : sort; import std.format : formattedWrite; auto r = appender!string; foreach(f; freq.keys.sort!"a>b") { auto key = freq[f]; r.formattedWrite("(%c) %s, %.1f\n", key, dict[key], f); } return r.data; } } void main() { alias index = char; alias rank = float; alias name = string; alias Dict = DICT!(index, rank, name); alias chr = Tuple!(index, rank, name); auto chrs = [ chr(44, 61.3, "Comma"), chr(34, 26.7, "Doublequote"), chr(39, 24.3, "Apostrophe"), chr(45, 15.3, "Hyphen"), chr(63, 5.6, "Question"), chr(58, 3.4, "Colon"), chr(33, 3.3, "Exclamation"), chr(59, 3.2, "Semicolon") ]; Dict enDict; foreach(tup; chrs) //multiple insertion enDict = tup; writeln("Frequency distributions of punctuation marks used in English: "); enDict = chr(46, 65.3, "Dot"); // single insertion enDict.writeln; } ``` SDB@79