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
Re: The difference between T[] opIndex() and T[] opSlice()
On Thursday, 5 October 2023 at 16:40:49 UTC, Gaurav Negi wrote: Well, in the D programming language, both opIndex and opSlice are two different operators used to access elements of a custom type. Yeah, D is on its way to becoming a near-perfect programming language... ```d enum initialSituation = [1, 2, 3]; import std.stdio; void main() { auto s = S(initialSituation); s[] = 1; s[1] = 2; s[2] += 2; assert(s.arr == initialSituation); auto d = s *= 2; assert(d == S([2, 4, 6])); } /* Prints: [1, 1, 1]: onlineapp.S.opSliceAssign [1, 2, 1]: onlineapp.S.opIndexAssign [1, 2, 1]: onlineapp.S.opIndex [2, 4, 6]: onlineapp.S.opOpAssign!"*".opOpAssign */ struct S { int[] arr; auto opSliceAssign (int value) { scope(exit) { writefln("%s: %s", arr, __FUNCTION__); } return arr[] = value; } auto opIndexAssign(int value, int index) { scope(exit) { writefln("%s: %s", arr, __FUNCTION__); } arr[index] = value; } ref opIndex(size_t index) { scope(exit) { writefln("%s: %s", arr, __FUNCTION__); } return arr[index]; } ref opOpAssign(string op)(int value) { scope(exit) { writefln("%s: %s", arr, __FUNCTION__); } mixin("arr[] " ~ op ~ "=value;"); return this; } } ``` SDB@79
Re: opIndexAssign
On Thursday, 5 October 2023 at 12:00:22 UTC, Timon Gehr wrote: void opIndexAssign(int value, int index){ i[index] = value; } In this case I need to define many operator overloads. For example (+=), this won't work without returns ref: ```d s[1] += 3; assert(s.i == [2, 45]); // Error: no `[]` operator overload for type `S` ``` SDB@79
Re: The difference between T[] opIndex() and T[] opSlice()
On Tuesday, 3 October 2023 at 18:09:55 UTC, Imperatorn wrote: At the very least, the spec should do a better job of documenting when the compiler will try a fallback and when it won't. Who will be the hero and add the documentation? More importantly, is there a priority order? Because in our last example, when we leave a single overload, all features are executed through the ref opIndex except the bit: ```d struct S { int[] i; ref opIndex(size_t index) => i[index]; //void opIndexAssign(int value) { i[] = value; } //void opIndexAssign(int value, size_t idx) { i[idx] = value; } } void main() { auto s = S([2, 2]); s[0] = 2; assert(s.i == [2, 2]); s[1] = 42; assert(s.i == [2, 42]); s[0]++; assert(s.i == [3, 42]); s[0] += 1; assert(s.i == [4, 42]); } ``` So the important thing is: Who is dominant when another overload comes into play? SDB@79
Re: Key and value with ranges
On Monday, 2 October 2023 at 20:20:44 UTC, Joel wrote: I want the output sorted by value. Look: https://forum.dlang.org/post/qjlmiohaoeolmoavw...@forum.dlang.org ```d struct SIRALA(T) { } ``` You can use SIRALA(T). Okay, his language is Turkish but our common language is D. His feature is that he uses double AA. You will like it. Here is the source: https://gist.github.com/run-dlang/808633909615dbda431baa01f795484f SDB@79
opIndexAssign
Hi, opIndexAssign, which is void, cannot compromise with opIndex, which is a ref! Solution: Using opSliceAssign. Could this be a bug? Because there is no problem in older versions (e.g. v2.0.83). ```d struct S { int[] i; ref opIndex(size_t index) => i[index]; auto opSliceAssign/* auto opIndexAssign//*/ (int value) => i[] = value; } void main() { auto s = S([1, 2]); s[] = 2; assert(s.i == [2, 2]); s[1] = 42; assert(s.i == [2, 42]); } ``` **Source:** https://run.dlang.io/is/G3iBEw If you converted comment line 7 with // and you will see this error: onlineapp.d(19): Error: function `onlineapp.S.opIndexAssign(int value)` is not callable using argument types `(int, int)` onlineapp.d(19):expected 1 argument(s), not 2 SDB@79
Re: The difference between T[] opIndex() and T[] opSlice()
On Monday, 2 October 2023 at 20:42:14 UTC, Paul Backus wrote: I don't know what's wrong in your example but this works for me: I found the reason for the error: https://forum.dlang.org/thread/vckvftkdzcrnikudu...@forum.dlang.org SDB@79
Re: The difference between T[] opIndex() and T[] opSlice()
On Monday, 2 October 2023 at 16:05:39 UTC, Paul Backus wrote: `T[] opSlice()` is the D1 version and exists only for backwards compatibility. You should use `T[] opIndex()` in new code. Forgive me for asking again, I think opSliceAssign(T value) has also been improved, right? ```d // ... auto opSlice() { return elements[]; } auto opSliceAssign(T value) { foreach(i; 0 .. length) { ptr[i] = value; } } } ``` In an old version (for example, v2.0.83), the code you implemented in the places where Slice is written above works as desired. In the most current versions, the parameterized opIndexAssign(T value) gives the error: onlineapp.d(51): Error: function `onlineapp.Matrix!double.Matrix.opIndexAssign(double value)` is not callable using argument types `(double, ulong)` onlineapp.d(51):expected 1 argument(s), not 2 **Source:** https://run.dlang.io/is/TPAg5m Thanks... SDB@79
Re: The difference between T[] opIndex() and T[] opSlice()
On Monday, 2 October 2023 at 02:01:34 UTC, Jonathan M Davis wrote: For most code, you'd just write an opIndex with a single parameter for indexing an element, opSlice with two parameters for slicing the range or container, and then either opIndex or opSlice with no parameters to return a slice of the entire container (in which case, personally, I'd use opSlice, because semantically, that's what you're doing, but either should work IIRC). Overloading has nothing to do with indexing, so I'll use opSlice. ```d import std.stdio; import std.range; struct Matrix(T) { private T[][] elements; size_t length; T* ptr; this(size_t length) { this.length = length * length; size_t m = T.sizeof * this.length; ubyte[] arr = new ubyte[](m); ptr = cast(T*)arr.ptr; m /= length; foreach(i; 0 .. length) { size_t n = i * m; elements ~= cast(T[])arr[n .. n + m]; } } ref T opIndex(size_t i) in(i < length) => ptr[i]; auto opDollar() => length; auto opSliceAssign(T value, size_t a, size_t b) in(a <= length && b <= length) => ptr[a..b] = value; auto opSlice() => elements; auto opSliceAssign(T value) { foreach(i; 0 .. length) { ptr[i] = value; } } } void main() { auto arr = Matrix!double(3); size_t n; foreach(value; iota(0.1, 1, 0.1)) arr[n++] = value; arr[].writefln!"%-(%-(%s %)\n%)\n"; arr[0..$/2] = 0; // reset a slice arr[].writefln!"%-(%-(%s %)\n%)\n"; arr[] = 0; // reset all arr[].writefln!"%-(%-(%s %)\n%)\n"; arr[6..9] = 1; // set a slice arr[].writefln!"%-(%-(%s %)\n%)\n"; } ``` SDB@79
Re: The difference between T[] opIndex() and T[] opSlice()
On Sunday, 1 October 2023 at 17:41:08 UTC, Salih Dincer wrote: Also, is it correct to use [] when returning? Thanks... [Here](https://dlang.org/spec/operatoroverloading.html#slice), the opIndex() is proposed and an example of parameterized the opSlice() is given for multidimensional arrays. Like there's no difference, huh? Puff :)
The difference between T[] opIndex() and T[] opSlice()
Hi, What is the difference between T[] opIndex() and T[] opSlice(), which haven't parameters? ```d struct S(T) { T[] arr; T[] opIndex() => arr[];/* T[] opSlice() => arr;//*/ } alias Type = int; void main() { auto s = S!Type([1,2,3]); auto arr = s[]; // calls s.opIndex() assert(arr == [1,2,3]); assert(is(typeof(arr): Type[])); } ``` Also, is it correct to use [] when returning? Thanks...
Re: Dinamyc arrays
On Sunday, 17 September 2023 at 17:15:34 UTC, Timofey wrote: I`ve just started learning d and have a question. What should I write to set dinamyc rectangular array length in both dimentions? For example, I have declareted an array: ``` int[][] matrix;``` and want set it as n*n matrix. Thanks There are many ways to do this, but I can quickly show you two: ```d import std.stdio; void main() { int[][] matrix; enum n = 6; // method 1: //matrix = new int[][](n, n); /* // method 2: matrix.length = n; foreach(ref e; matrix) e.length = n;//*/ matrix.writeln; } ``` SDB@79
Re: Setting struct as default parameter of a function using struct literal?
On Monday, 11 September 2023 at 23:47:33 UTC, H. S. Teoh wrote: Since the type of the parameter is already known, the compiler does not need me to repeat the type name. It already knows enough to figure it out on its own. "Don't Repeat Yourself" (DRY). I think there are 3 possibilities, leaving aside what Steven suggested. Well, since these options will generally be static, why not use a template parameter? Besides, everything can be expressed with a single letter. For example: ```d // Steven suggested... void multiParams(bool silenceErrors = false, bool otherOption = true) { writeln; } // (1) It cannot be customized. auto someFunction(Options option = Options.init) => option;//*/ /*/ (2a) It doesn't run older versions: auto someFunction(Options option = Options(silenceErrors: false)) => option;//*/ /*/ (2b) There's a possibility of confusion: auto someFunction(Options option = Options (false, false) => option;//*/ struct Options { bool silenceErrors = true; bool printDebugs = true; string toString() => format("silenceErrors: %s\nprintDebugs: %s", silenceErrors, printDebugs); } import std.format, std.stdio; void main() { auto foo(T, T option = T.init)() => option; writeln(foo!Options); writeln(someFunction); } ``` SDB@79
Re: Setting struct as default parameter of a function using struct literal?
On Monday, 11 September 2023 at 22:13:25 UTC, H. S. Teoh wrote: Because sometimes I want a specific type. it's possible... ```d alias ST = Options; void specificType(ST option = ST()) { if(option) { assert(false); } else assert(true); } void main() { specificType(); // No error specificType(ST.silenceErrorsOn); // assert failure } ``` SDB@79
Re: Setting struct as default parameter of a function using struct literal?
On Monday, 11 September 2023 at 20:17:09 UTC, H. S. Teoh wrote: Someone should seriously come up with a way of eliminating the repeated type name in default parameters. Why not allow it to be flexible enough by using a template parameter? ```d enum Options : bool { silenceErrorsOff, silenceErrorsOn } struct Opts { bool silenceErrors; } void someFunction(T)(T option = T()) { import std.stdio; writeln(cast(bool)option); // true } void main() { Opts o; someFunction(o.silenceErrors = true); with(Options) someFunction(silenceErrorsOn); } ``` SDB@79
Re: Setting struct as default parameter of a function using struct literal?
On Monday, 11 September 2023 at 17:51:04 UTC, BoQsc wrote: Here is an example of what I would hope for to work but it surely does not work: If I were you I would use enum, look at my code: ```d enum Options { silenceErrors = false } void someFunction (Options option = Options.silenceErrors) { writeln(cast(bool)option); // false } import std.stdio; void main() { someFunction(); } ``` SDB@79
Re: class Object with Dependency Injection
On Sunday, 18 June 2023 at 16:58:15 UTC, Ali Çehreli wrote: The problem is with the deduced type of 'services'. I don't know the mechanism behind it but the common type of 'truck' and 'ship' are deduced to be Object. Apparently, their interfaces don't take part in that decision. I don't know why. This is very interesting because it looks like a bug. Why is there no problem in an abstracted object, but things get confused in the interface (ITransport)? On Sunday, 18 June 2023 at 16:58:15 UTC, Ali Çehreli wrote: One solution is to help the compiler by casting them to your desired interface: In fact, there is no need to cast: ```d interface ITransport { string deliver(); } //... void main() { auto truck = new Truck; ITransport ship = new Ship; /* or ITransport truck = new Truck; auto ship = new Ship; // or ITransport truck = new Truck; ITransport ship = new Ship;//*/ } ``` SDB@78
class Object with Dependency Injection
Hi, below is an example of DI-dependency injection with 3 versions nested in the code. If you remove the leading // characters, you will not get the "no property `deliver` for `service` of type `object.Object`" error. Because version-2I with interface wants its methods to depend on Object.. ```d //abstract class /* toggle-code interface //* ^---version 2A */ ITransport { string deliver(); } class Ship : ITransport { override string deliver() { return "Ship Deliver"; } } class Truck : ITransport { override string deliver() { return "Truck Deliver"; } } abstract class Logistics { ITransport createTransport(); auto operations() { return createTransport.deliver(); } } class RoadLogistics : Logistics { override ITransport createTransport() { return new Truck(); } } class SeaLogistics : Logistics { override ITransport createTransport() { return new Ship(); } } import std.stdio; void main() { // DI version 1: auto sl = new SeaLogistics; auto rl = new RoadLogistics; auto logistics = [ sl, rl ]; foreach(deliver; logistics) { auto str = deliver.operations(); str.length.writeln(": ", str); } import std.range : repeat; "÷ ".repeat(9).writefln!"%-(%s%)"; // A->I version 2: auto truck = new Truck; auto ship = new Ship; auto services = [ truck, ship ]; foreach(service; services) { auto str = service.deliver(); str.length.writeln(": ", str); } } ``` Maybe using an abstract class instead of interface or not using auto will solve the problem, but I can't accept the situation! I wonder what makes the interface special? SDB@79
Re: byte and short data types use cases
On Friday, 9 June 2023 at 23:51:07 UTC, Basile B. wrote: Yes, a classsic resource is http://www.catb.org/esr/structure-packing/ So you can optimize memory usage by using arrays of things smaller than `int` if these are enough for your purposes, So, is the sorting correct in a structure like the one below with partial overlap? ```d struct DATA { union { ulong bits; ubyte[size] cell; } enum size = 5; bool last; alias last this; size_t length, limit, index = ulong.sizeof; bool empty() { return index / ulong.sizeof >= limit; } ubyte[] data; ubyte front() { //.. ``` This code snippet is from an actual working my project. What is done is to process 40 bits of data. SDB@79
Re: Proper way to handle "alias this" deprecation for classes
On Wednesday, 17 May 2023 at 08:00:17 UTC, Dom DiSc wrote: If you want auto-conversion, you should be more explicit: ```d float opCast() { } ``` because if you return "auto" it is not the highest-prio fit and therefore not chosen. If you have multiple choices, you still don't need to use "auto". Instead you can return T: ```d T opCast(T)() if(isFloatingPoint!T) { return cast(T)num / cast(T)den; // float, double or real } ``` Kind of ironic, but especially "auto" does NOT fit automatically :-) Sorry for not expressing myself better. Let me try to explain with another example: ```d struct RightShift { int num, shr; T opCast(T : char)() => cast(T)(num >> shr); } import std.stdio; void main() { auto f = RightShift(128, 2); char chr = cast(char)f | '\1'; assert(chr == '!'); //char test = f; // Error: cannot implicitly convert expression //assert(test == ' '); // `f` of type `RightShift` to `char` } ``` This snippet works fine. But hidden the code gives an error. The reason is that the compiler ignores the explicitly specified lines without using auto. SDB@79
Re: Proper way to handle "alias this" deprecation for classes
On Sunday, 7 May 2023 at 21:04:05 UTC, Inkrementator wrote: Open question to everybody: What you're opinion on using opCast for this? Since it's a type conversion, it seems fitting to me. Can't converting without explicitly specifying in D is a big shortcoming in my opinion. There is such a thing as implicitly convertion though, but it's very confusing. I don't see that simplicity in C++ in the D codes! ```CPP #include using namespace std; struct Fraction { int num, den; Fraction(int n, int d) { num = n; den = d; } // Conversion operator: return float value of fraction operator float() const { return float(num) / float(den); } }; int main() { Fraction f(2, 5); float val = f; cout << val << '\n'; // 0.4 return 0; } ``` You should do the same in D like this: ```d struct Fraction { int num, den; this(int n, int d) { num = n; den = d; } // Cast Expression : convert float value of fraction auto opCast(T : float)() const { return cast(float)(num) / cast(float)(den); } } import std.stdio; int main() { auto f = Fraction(2, 5); float val = cast(float)f; val.writeln; //0.4 return 0; } ``` SDB@79
Re: Getting a total from a user defined variable
On Friday, 21 April 2023 at 05:23:14 UTC, Joel wrote: Or: p.map!"a.age".sum; works too. If it was me I would use each(). But D is such a powerful language that you have many alternatives: ```d import std.algorithm, std.range, std.stdio; struct Person { string name; int age; } auto totalPersonAge = (int result, Person person) => result + person.age; void main() { auto p = [ Person("Kocaeli", 41), Person("Konya", 42) ]; p.map!(a => a.age).reduce!"a + b".writeln; p.map!"a.age".reduce!"a + b".writeln; auto result = reduce!((a, b) => a + b.age)(0, p); result.writeln; assert(result == reduce!totalPersonAge(0, p)); assert(result == p.fold!totalPersonAge(0)); assert(p.map!(a => a.age).sum == p.map!"a.age".sum); size_t total; p.each!( (ref person) => total += person.age); total.writeln; } ``` SDB@79
Re: Variable length arrays under -betterC?
On Monday, 17 April 2023 at 19:12:20 UTC, user456 wrote: ... but you'll have to implement - ctors - concat assign - slice assign - copy construction - value type elem alignment - default elem construction - default elem destruction - etc. to make that usable in on trivial cases. I understand from the thread this: D gives us -betterC but nothing from the Phobos. So he says, see what you have, do what the hell you want! Am I wrong about this? SDB@79
Re: vibe.db.postgresql: Example not working in Windows
On Friday, 14 April 2023 at 17:06:36 UTC, Vino wrote: I was just trying the new package vibe.db.postgresql and the example provided is not working, can some one provide me an working example. Step performed ``` dub init dub add vibe-d-postgresql copy the example program to source/app.d dub run ``` I would like to draw your attention to this point: ```d #!/usr/bin/env dub /+ dub.sdl: dependency "vibe-d" version="~>0.9.0" +/ void main() { import vibe.d; listenHTTP(":8080", (req, res) { res.writeBody("Hello, World: " ~ req.path); }); runApplication(); } ``` Do you have a working vibe app? SDB@79
Re: Unresolvable dependencies to package
On Friday, 14 April 2023 at 20:30:56 UTC, el machine code wrote: so my question why am i'm getting this error and how do i fix this? As far as I know imGUI works with SFML. First, please appear a Japanese flag on your screen: https://forum.dlang.org/post/apledbmyzlxsdaaow...@forum.dlang.org SDB@79
Re: How to setup D with SFML? (using bindbc-sfml)
On Friday, 14 April 2023 at 12:26:25 UTC, Ki Rill wrote: Yay! That worked! Now I have a working example. Though it's strange that it does not work with shared libs. Good luck, I'm really happy for you... Ki Rill, wait a minute! Actually, i've been very happy for the D community. Because I really appreciate what you've done. You are an idealistic person and please stay that way. We can do more things. SDB@79
Re: How to setup D with SFML? (using bindbc-sfml)
On Friday, 14 April 2023 at 00:28:53 UTC, Ki Rill wrote: ``` LINK : fatal error LNK1104: cannot open file 'libucrt.lib' Error: linker exited with status 1104 ``` Why does it require this library and where can I find it? Since this library is a component of the Microsoft C Runtime (CRT) library, you may need to install this library. To install the CRT library, follow these steps: * Download and install the latest version of Microsoft Visual Studio. * In the Visual Studio installer, install the "C++ Universal CRT" component under "Workloads > Desktop development with C++". * Restart the build and check if the error is resolved. **Source:** https://stackoverflow.com/questions/44763817/link-fatal-error-lnk1104-cannot-open-file-ucrt-lib SDB@79
Re: Assocative array lookup for object
On Wednesday, 12 April 2023 at 13:09:07 UTC, Ali Çehreli wrote: Not every type is null'able but nullable. ;) So, a design may use the following: https://dlang.org/library/std/typecons/nullable.html I implemented Handler into the Voldermort build, which Walter loved so much. For convenience, I put an alias between the template and the function. But Nullable didn't work, instead it's returning T.init... ```d template Handler(alias A) { alias T = typeof(A); auto Handler() { struct Impl { T*[string] data; void set(string key, ref T value) { data[key] = } auto opIndex(string key) { if (auto ret = key in data) { return **ret; } return T.init;/* import std.typecons : Nullable; return Nullable!T.init;//*/ } auto opSlice() { T[] result; foreach (ref value; data.values) result ~= *value; return result; } } return Impl(); } } import std.stdio; void main() { struct List { string product; float price; } auto fruits = [ List("Manderin", 3.79), List("Orange", 2.99), List("Kiwi", 0.59), ]; auto handlers = Handler!fruits; handlers.set("fruits", fruits); // please try it: ^--v foreach(h; handlers["fruit"]) { h.product.write(": "); h.price.writeln(" €"); } auto handler = Handler!(List()); import std.conv : text; foreach(i, ref fruit; fruits) { handler.set(i.text, fruit); } handler[].writeln; } /* Prints: Manderin: 3.79 € Orange: 2.99 € Kiwi: 0.59 € [List("Kiwi", 0.59), List("Manderin", 3.79), List("Orange", 2.99)] */ ``` SDB@79
Re: Assocative array lookup for object
On Wednesday, 12 April 2023 at 04:57:58 UTC, Salih Dincer wrote: I think you want to do an encapsulation like below. ```d auto opIndex(string key) => *(key in data); ``` I made a little mistake and I'll fix it before someone rub nose in it :) ```d auto opIndex(string key) { if(auto ret = key in data) { return *ret; } return null; } assert(handler["D Lang"] == ); assert(handler["null"] is null); ``` SDB@79
Re: How to setup D with SFML? (using bindbc-sfml)
On Tuesday, 11 April 2023 at 10:24:09 UTC, Ki Rill wrote: My `dub.json`: ```Json { "authors": [ "rillki" ], "copyright": "Copyright © 2023, rillki", "dependencies": { "bindbc-sfml": "~>1.0.2" }, "description": "D/SFML project template", "license": "BSL", "name": "d-sfml-project-template", "targetPath": "bin", "versions": [ "SFML_Audio", "SFML_Graphics", "SFML_Network", "SFML_System", "SFML_Window", "SFML_250" ] } ``` I will try to make it work... Meanwhile, if someones spots what I am doing wrong, please reply to this post. If I use your dub.json, my terminal screen says: user@debian:~/Downloads$ cd dsfml user@debian:~/Downloads/dsfml$ dub Fetching bindbc-sfml 1.0.2 (getting selected version) Fetching bindbc-loader 1.0.3 (getting selected version) Starting Performing "debug" build using /usr/bin/dmd for x86_64. Building bindbc-loader 1.0.3: building configuration [noBC] Building bindbc-sfml 1.0.2: building configuration [dynamic] Building d-sfml-project-template ~master: building configuration [application] Linking d-sfml-project-template Running bin/d-sfml-project-template Error Program exited with code -11 If I add "BindSFML_Static" to the DUB's version directive, I switch to static, which I guess you don't want. But then I also get a bunch of undefined errors: /usr/bin/ld: /home/user/.dub/cache/d-sfml-project-template/~master/build/application-debug-TGcRCxHHanKq_MbfWLee8g/d-sfml-project-template.o: in function `_Dmain': /home/user/Downloads/dsfml/source/app.d:11: undefined reference to `sfRenderWindow_create' ... collect2: error: ld returned 1 exit status Error: linker exited with status 1 Error /usr/bin/dmd failed with exit code 1. If you wanted static I would add and run libraries easy, like this: ```Json "libs": [ "csfml-audio", "csfml-graphics" ], "versions": [ "SFML_Audio", "SFML_Graphics", "BindSFML_Static", ] } ``` In summary, DUB takes care of everything for us. It should be same in W$... SDB@79
Re: Assocative array lookup for object
On Wednesday, 12 April 2023 at 01:16:17 UTC, Chris Katko wrote: Should I be using opEquals? Or something different? The problem with 'alias this' here is I want to wrap access to the insides with getter functions that do various things like logging and error checking. I think you want to do an encapsulation like below. ```d class Handler(T) { T*[string] data; auto set(string key, ref T value) => data[key] = auto opIndex(string key) => *(key in data); } void main() { class Bitmap {} Bitmap foo; auto handler = new Handler!Bitmap; handler.set("D Lang", foo); assert(handler["D Lang"] == ); } ``` SDB@79
Re: How to setup D with SFML? (using bindbc-sfml)
On Saturday, 8 April 2023 at 23:40:32 UTC, Mike Parker wrote: Not without error messages. The first thing you should do is use the error API in bindbc.loader to print them out. That should tell you what the problem is. I installed it on my Linux system without using a loader and with static SFML. I just used apt-get and dub. I did the following in order: 1. sudo apt-get install libsfml-dev libcsfml-dev 2. dub init dsfml bindbc-sfml 3. cd dsfml 4. edit dub.json and add: ```java "libs": [ "csfml-audio", "csfml-graphics" ], "subConfigurations": { "bindbc-sfml": "staticBC" }, "versions": [ "SFML_Audio", "SFML_Graphics" ], ``` 5. dub **app.d** ```d import bindbc.sfml; void main() { sfContextSettings* settings; sfEvent event; auto window = sfRenderWindow_create( sfVideoMode(750, 500), "Japanese Flag", sfWindowStyle.sfDefaultStyle, settings ); auto flag = sfCircleShape_create(); flag.sfCircleShape_setRadius(150); flag.sfCircleShape_setPosition(sfVector2f(225, 100)); flag.sfCircleShape_setFillColor(sfRed); while(window.sfRenderWindow_isOpen()) { while(window.sfRenderWindow_pollEvent()) { if(event.type == sfEventType.sfEvtClosed) { window.sfRenderWindow_close(); } } window.sfRenderWindow_clear(sfWhite); window.sfRenderWindow_drawCircleShape(flag, null); window.sfRenderWindow_display(); } } ``` SDB@79
Re: member func is best choice for pointers?
On Thursday, 6 April 2023 at 14:26:01 UTC, a11e99z wrote: member func has invariant that **this** is not null (programmer thinks so). global func hasn't the one and programmer should check for it before doing something ... I understand what you mean. When you try to access the last node of a linked list, you will get the segmentation fault if you are using a built-in viewer (toString). For example: ```d struct Node { int item; Node * back; string toString() { import std.format : format; return format("Node::%s (back)-> %s", item, back.item); } } void main() { import std.stdio : writeln; auto node1 = Node(41); auto node1Ptr = //printNode(node1Ptr);/* NOT COMPILE! node1.writeln;//* Main::41 (back)-> null */ auto node2 = Node(42); node2.back = node1Ptr; printNode(); // Main::42 (back)-> 41 node2.writeln; // Node::42 (back)-> 41 } void printNode(Node * p) { import std.stdio : writefln; if(p.back is null) { writefln("Main::%s (back)-> null", p.item); } else { writefln("Main::%s (back)-> %s", p.item, p.back.item); } } ``` If you don't remove the comment line (just remove the // sign: toggle-comment) the above code will not compile. Because it is not connect to any node. @SDB
Re: constant pointer failing to compile
On Thursday, 6 April 2023 at 00:46:26 UTC, Josh Holtrop wrote: ``` constarrptr.d(5): Error: cannot use non-constant CTFE pointer in an initializer `cast(immutable(ubyte)*)data` ``` Why? And how can I do the equivalent to what I have been doing in C? I want these pointers to be generated at compile time, not initialized at runtime. (the full project is generating this file containing the data array (which is much longer) and multiple pointer constants to locations within it) You have 2 options: First, to use .ptr, or second, to do the initialization in static this: ```d import std.stdio; static const char[] d; static const char * p; static this() { d = [97, 98, 99]; p = [0]; // == d.ptr; } void main() { printf("%.*s\n", cast(int)d.length, d.ptr); writeln("*p = ", *p); }/* Prints: abc *p = a */ ``` SDB@79
Re: foreach (i; taskPool.parallel(0..2_000_000)
On Tuesday, 4 April 2023 at 16:22:29 UTC, Steven Schveighoffer wrote: On 4/4/23 11:34 AM, Salih Dincer wrote: On Tuesday, 4 April 2023 at 14:20:20 UTC, Steven Schveighoffer wrote: parallel is a shortcut to `TaskPool.parallel`, which is indeed a foreach-only construct, it does not return a range. I think what you want is `TaskPool.map`: ```d // untested, just looking at the taskPool.map!(/* your map function here */) (s.iota(len)).writeln; ``` I tried, thanks but it goes into infinite loop. For example, the first 50 of the sequence should have been printed to the screen immediately without waiting. ```d long[50] arr; RowlandSequence_v2 range; auto next(long a) { range.popFront(); return arr[a] = range.front(); } void main() { range = RowlandSequence_v2(7, 2); taskPool.map!next(iota(50))/* s.iota(50) .map!next .parallel//*/ .writeln; } ``` Keep in mind that `arr` and `range` are thread-local, and so will be different states for different tasks. I guess the reason it goes into an infinite loop is because gcd() a recursive function (gcd). This is the only solution I can think of about this: ```d import std.range, std.algorithm : map; import std.stdio, std.parallelism; //import std.numeric : gcd; /* struct Vector { long x, y, result; alias result this; } Vector gcd(long a, long b) { if(b == 0) return Vector(1, 0, a); auto pre = gcd(b, a % b); auto tmp = (a / b) * pre.y; return Vector(pre.y, pre.x - tmp, pre.result); }//*/ struct RowlandSequence_v3 { long b, r, n, a = 3, limit; bool empty() { return n == limit; } auto front() { return a; } void popFront() { long result = 1; while(result == 1) { result = gcd(r++, b); b += result; } a = result; } long gcd(long a, long b) { long c; while(b != 0) { c = a % b; a = b; b = c; } return a; } } auto next(ref RowlandSequence_v3 range) { with(range) { if(empty) return [n, front]; popFront(); return [n++, front]; } } long[179] arr; void main() { // initialization: RowlandSequence_v3[4] r = [ RowlandSequence_v3(7 , 2, 0, 3, 112), RowlandSequence_v3(186837678, 62279227, 112, 3, 145), RowlandSequence_v3(747404910, 249134971, 145, 6257, 160), RowlandSequence_v3(1494812421, 498270808, 160, 11, 177) ]; auto tasks = [ task(, r[0]), task(, r[1]), task(, r[2]), task(, r[3]) ]; // quad parallel operation: foreach(_; 0..r[0].limit) { foreach(p, ref task; tasks) { task.executeInNewThread; auto t = task.workForce; arr[t[0]] = t[1]; } } // prints... foreach(x, n; arr) { switch(x + 1) { case 112, 145, 160: n.writeln; break; default: n.write(", "); } } } /* PRINTS: user@debian:~/Documents$ dmd -O rowlandSequence.d -release user@debian:~/Documents$ time ./rowlandSequence 5, 3, 11, 3, 23, 3, 47, 3, 5, 3, 101, 3, 7, 11, 3, 13, 233, 3, 467, 3, 5, 3, 941, 3, 7, 1889, 3, 3779, 3, 7559, 3, 13, 15131, 3, 53, 3, 7, 30323, 3, 60647, 3, 5, 3, 101, 3, 121403, 3, 242807, 3, 5, 3, 19, 7, 5, 3, 47, 3, 37, 5, 3, 17, 3, 199, 53, 3, 29, 3, 486041, 3, 7, 421, 23, 3, 972533, 3, 577, 7, 1945649, 3, 163, 7, 3891467, 3, 5, 3, 127, 443, 3, 31, 7783541, 3, 7, 15567089, 3, 19, 29, 3, 5323, 7, 5, 3, 31139561, 3, 41, 3, 5, 3, 62279171, 3, 7, 83, 3 29, 3, 1103, 3, 5, 3, 13, 7, 124559609, 3, 107, 3, 911, 3, 249120239, 3, 11, 3, 7, 61, 37, 179, 3, 31, 19051, 7, 3793, 23, 3, 5, 3, 6257, 3 3, 11, 3, 13, 5, 3, 739, 37, 5, 3, 498270791, 3, 19, 11, 3 3, 3, 5, 3, 996541661, 3, 7, 37, 5, 3, 67, 1993083437, 3, 5, 3, 83, 3, 3, 0, real7m54.093s user7m54.062s sys 0m0.024s */ ``` However, parallel processing for 4-digit sequence elements is not promising at least for the Rowland Sequence. SDB@79
Re: foreach (i; taskPool.parallel(0..2_000_000)
On Tuesday, 4 April 2023 at 14:20:20 UTC, Steven Schveighoffer wrote: parallel is a shortcut to `TaskPool.parallel`, which is indeed a foreach-only construct, it does not return a range. I think what you want is `TaskPool.map`: ```d // untested, just looking at the taskPool.map!(/* your map function here */) (s.iota(len)).writeln; ``` I tried, thanks but it goes into infinite loop. For example, the first 50 of the sequence should have been printed to the screen immediately without waiting. ```d long[50] arr; RowlandSequence_v2 range; auto next(long a) { range.popFront(); return arr[a] = range.front(); } void main() { range = RowlandSequence_v2(7, 2); taskPool.map!next(iota(50))/* s.iota(50) .map!next .parallel//*/ .writeln; } ``` On Tuesday, 4 April 2023 at 13:18:01 UTC, Ali Çehreli wrote: I don't have time to experiment more at this time but I have the following chapters, which includes some of those other algorithms as well: http://ddili.org/ders/d/kosut_islemler.html I read it, thanks... SDB@79
Re: foreach (i; taskPool.parallel(0..2_000_000)
On Monday, 3 April 2023 at 22:24:18 UTC, Steven Schveighoffer wrote: So for example, if you have: ```d foreach(i; iota(0, 2_000_000).parallel) { runExpensiveTask(i); } ``` The foreach is run on the main thread, gets a `0`, then hands off to a task thread `runExpensiveTask(0)`. Then it gets a `1`, and hands off to a task thread `runExpensiveTask(1)`, etc. The iteration is not expensive, and is not done in parallel. On the other hand, what you *shouldn't* do is: ```d foreach(i; iota(0, 2_000_000).map!(x => runExpensiveTask(x)).parallel) { } ``` as this will run the expensive task *before* running any tasks. I don't understand what `foreach()` does :) ```d import std.range, std.algorithm : map; import std.stdio, std.parallelism; //import sdb.sequences : RowlandSequence_v2;/* struct RowlandSequence_v2 { import std.numeric : gcd; long b, r, a = 3; enum empty = false; auto front() => a; void popFront() { long result = 1; while(result == 1) { result = gcd(r++, b); b += result; } a = result; } }//*/ enum BP : long { // s, f, r, b = 7, /* <- beginning s = 178, r = 1993083484, b = 5979250449,//*/ len = 190 } void main() { with(BP) { long[len] arr; auto range = RowlandSequence_v2(b, r); s.iota(len) .map!((a){ range.popFront(); return arr[a] = range.front(); } ) .parallel .writeln; } } /* PRINTS: ParallelForeach!(MapResult!(__lambda3, Result))(std.parallelism.TaskPool, [5, 3, 73, 157, 7, 5, 3, 13, 3986167223, 3, 7, 73], 1) */ ``` Is it necessary to enclose the code in `foreach()`? I invite Ali to tell me! Please explain why parallel isn't running. "Ben anlamıyor, foreach ne yapıyor Kodu `foreach()` içine almak şart mı? Ali'yi davet ediyorum, bana anlatması için! Paralel() niye çalışmıyor, lütfen açıklayın hocam. Mümkünse Türkçe!" in Turkish. SDB@79
Re: short guide on getting started with D
On Monday, 3 April 2023 at 07:29:01 UTC, cgenie wrote: Thanks, you got my attention... It has come to my attention that you talked about this: https://mesonbuild.com/Dlang-module.html SDB@79
Re: foreach (i; taskPool.parallel(0..2_000_000)
On Sunday, 2 April 2023 at 04:34:40 UTC, Salih Dincer wrote: I haven't seen rsFirst256 until now... **Edit:** I saw, I saw :) I am struck with consternation! I've never seen these results before. Interesting, there is such a thing as parallel threading :) Here are my skipPoints: ```d enum BP : long { //f, a, r, b = 7, /* <- beginning f = 113, r = 62279227, b = 186837678, // f = 146, r = 249134971, b = 747404910, // f = 161, r = 498270808, b = 1494812421, // f = 178, r = 1993083484, b = 5979250449, // f = 210, r = 3986167363, b = 11958502086, //*/ s = 5 } /* PRINTS: eLab@pico:~/Projeler$ ./RownlandSequence_v2 122: ["124559610, 373678827"] 128: ["249120240, 747360717"] */ ``` It looks like there are 5 total skipPoints until 256 where it loops for a long time. (while passing 1's). SDB@79
Re: foreach (i; taskPool.parallel(0..2_000_000)
On Saturday, 1 April 2023 at 22:48:46 UTC, Ali Çehreli wrote: On 4/1/23 15:30, Paul wrote: > Is there a way to verify that it split up the work in to tasks/threads > ...? It is hard to see the difference unless there is actual work in the loop that takes time. I always use the Rowland Sequence for such experiments. At least it's better than the Fibonacci Range: ```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++; } } /* PRINTS: 46: ["121403", "364209, 121404"] 48: ["242807", "728421, 242808"] 68: ["486041", "1458123, 486042"] 74: ["972533", "2917599, 972534"] 78: ["1945649", "5836947, 1945650"] 82: ["3891467", "11674401, 3891468"] 90: ["7783541", "23350623, 7783542"] 93: ["15567089", "46701267, 15567090"] 102: ["31139561", "93418683, 31139562"] 108: ["62279171", "186837513, 62279172"] */ ``` The operation is simple, again multiplication, addition, subtraction and module, i.e. So four operations but enough to overrun the CPU! I haven't seen rsFirst256 until now because I don't have a fast enough processor. Maybe you'll see it, but the first 108 is fast anyway. **PS:** Decrease value of the `skip` to see the entire sequence. In cases where your processor power is not enough, you can create skip points. Check out BP... SDB@79
Re: InputRange in arrays
On Friday, 31 March 2023 at 04:15:24 UTC, Salih Dincer wrote: ...has it always been possible for arrays to be used as if they were ranges? Playground is a very useful tool, it responds right away :) Up to 2.078.3: Failure with output: - onlineapp.d(4): Error: no property 'popFront' for type 'int[]' onlineapp.d(6): Error: no property 'front' for type 'int[]' - 2.079.1 to 2.087.1: Failure with output: - onlineapp.d(4): Error: no property `popFront` for type `int[]` onlineapp.d(6): Error: no property `front` for type `int[]` - Since 2.088.1: Failure with output: - onlineapp.d(4): Error: no property `popFront` for type `int[]`, perhaps `import std.range;` is needed? onlineapp.d(6): Error: no property `front` for type `int[]`, perhaps `import std.range;` is needed? - SDB@79
Re: InputRange in arrays
On Friday, 31 March 2023 at 03:39:51 UTC, Salih Dincer wrote: May be somewhere D compiler between v2.087 and v2.096 (works) but definitely not before v2.087 (including)... Edit: The Phobos library I'm using is corrupted. That's why the last line was giving an error. But has it always been possible for arrays to be used as if they were ranges? Thanks... SDB@79
InputRange in arrays
Hi, there is a feature when working with the InputRange. I don't know when it released available. May be somewhere D compiler between v2.087 and v2.096 (works) but definitely not before v2.087 (including)... Anyone know this? ```d import std.range.primitives; void main() { auto arr = [0, 1]; arr.popFront; assert(arr.front == 1); assert(isInputRange!(typeof(arr))); } ``` SDB@79
Re: The Phobos Put
On Thursday, 30 March 2023 at 13:27:33 UTC, Steven Schveighoffer wrote: But you can do `dig.copy(buf[])` since a dynamic array is. Apparently, we will not be able to get rid of the necessity of using slices. Neither with "copy" nor with "put"... ```d import std.algorithm.mutation : copy; import std.range.primitives : put; void main() { int[8] buf;// = new int[8]; auto dig = [1, 2, 3, 4]; //dig.copy(buf[2..$-2]);/* auto slice = buf[2..$-2]; dig.copy(slice); assert(buf == [0, 0, 1, 2, 3, 4, 0, 0]); buf = 0; slice.put(dig);//*/ assert(buf == [0, 0, 1, 2, 3, 4, 0, 0]); } ``` SDB@79
Re: The Phobos Put
On Wednesday, 29 March 2023 at 20:50:04 UTC, Steven Schveighoffer wrote: On 3/29/23 4:29 PM, ag0aep6g wrote: But regardless of Salih's exact intent, the broader point is: a non-ref overload could be added to Phobos. And that would enable `a[1..$-1].phobos_put([2, 3])`. Which is what he asked about originally. I think the idea of requiring ref output ranges is that you can then let the range keep track of its output state. So why not copying the range to a static array? The error during compilation of the code is as follows: onlineapp.d(6): Error: none of the overloads of template `std.algorithm.mutation.copy` are callable using argument types `!()(int[], int[8])` /dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/mutation.d(367): Candidate is: `copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)` with `SourceRange = int[], TargetRange = int[8]` must satisfy the following constraint: ` isOutputRange!(TargetRange, ElementType!SourceRange)` ```d import std.algorithm.mutation : copy; void main() { int[8] buf; auto dig = [1, 2, 3, 4]; auto rem = dig.copy(buf); assert(rem.length == 4); } ``` Looks like 'copy' has the same overload issue. SDB@79
Re: How to debug and watch globals in windows debugger?
On Wednesday, 29 March 2023 at 21:09:57 UTC, ryuukk_ wrote: Also it's more of an accumulation of problems that makes me very annoyed https://issues.dlang.org/show_bug.cgi?id=20737 This for example shouldn't be a thing in 2023, period I agree with you because it's such a simple problem and it's surprising if it exists. I've never used -betterC though, but it's a pity. SDB@79
Re: The Phobos Put
On Wednesday, 29 March 2023 at 20:29:24 UTC, ag0aep6g wrote: But regardless of Salih's exact intent, the broader point is: a non-ref overload could be added to Phobos. And that would enable `a[1..$-1].phobos_put([2, 3])`. Which is what he asked about originally. Yes, that was it, but even more. Both functions serve the same thing. Why don't we combine them? SDB@79
Re: The Phobos Put
On Wednesday, 29 March 2023 at 19:49:47 UTC, Ali Çehreli wrote: On 3/29/23 12:21, ag0aep6g wrote: > As far as I understand, you're saying that we cannot overload on `ref`. > But we can. Salih's code demonstrates just that. > > void f(ref int x) {} > void f(int x) {} > void main() { int x; f(x); f(42); } /* no errors */ I thought Salih was proposing two more overloads to the existing put(). When I copy the existing put(), which takes 'ref R', not R[], then the code does not compile: Wait a minute, isn't `copy` actually a `put` as well? Forget about `ref` for a moment, please. Actually, logically, the parameters have been swapped between the two functions. Well, if we only had `copy` and we used `put` like `copy`, what is the need for `put`? Examples are below: :) ```d //version = simple;/* version = standart;//*/ version(simple) { auto put(R)(R[] range, R[] source) => copyImpl(source, range); auto copy(R)(R[] source, R[] range) => copyImpl(source, range); auto copyImpl(R)(R[] source, R[] range) { assert(source.length <= range.length); foreach(element; source) { range[0] = element; // range.front() range = range[1..$]; // range.popFront() } return range; } void swap (ref int x, ref int y) { x = x ^ y; y = y ^ x; x = x ^ y; } } version(standart) import std.algorithm.mutation, std.range : put; void main() { // copy() example: enum len = 10; auto buf = new int[len]; // buffer auto dig = [7, 1, 2, 3]; // digits auto diff = len - dig.length; auto rem = copy(dig, buf); assert(buf[0..$ - diff] == [7, 1, 2, 3]); swap(buf[0], rem[0]); assert(rem == [7, 0, 0, 0, 0, 0]); // put() example 1: put(rem, [4, 5, 6, 7, 8, 9]); assert(buf == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); // put() example 2: enum data = [1, 0, 0, 4]; auto arr = data; auto slice = arr[1..$-1]; version(standart) put(slice, [2]); version(simple) slice = put(slice, [2]); assert(arr == [1, 2, 0, 4]); version(standart) put(slice, [3]); version(simple) slice = put(slice, [3]); assert(arr == [1, 2, 3, 4]); version(standart) { auto slc = arr[1..$-1]; put(slc, [0, 0]); } version(simple) arr[1..$-1].put([0, 0]); assert(arr == data); } ``` All you have to do is remove the // mark in the first line. The code compiles for me, what about you? SDB@79
Re: The Phobos Put
On Wednesday, 29 March 2023 at 15:01:27 UTC, Ali Çehreli wrote: On 3/29/23 04:48, Dennis wrote: On the other hand, Phobos's put() works with any OutputRange so it has to take a 'ref' to advance to know where it is left off. This behavior makes its use with slices weird but sometimes such is life. :) Would not adding a prototype without a ref cause ambiguity? In this way, it could also be used directly with slices. For example: ```d auto put(R)(R[] range, R[] source) => putImpl(range, source); auto put(R)(ref R[] range, R[] source) => putImpl(range, source); void putImpl(R)(ref R[] range, R[] source) { assert(source.length <= range.length); foreach(element; source) { range[0] = element; // range.front() range = range[1..$]; // range.popFront() } } void main() { enum data = [1, 0, 0, 4]; auto arr = data; auto slice = arr[1..$-1]; slice.put([2]); assert(arr == [1, 2, 0, 4]); slice.put([3]); assert(arr == [1, 2, 3, 4]); arr[1..$-1].put([0, 0]); assert(arr == data); } ``` SDB@79
The Phobos Put
Why does my `put` work but the Phobos `put` doesn't work with a slice? onlineapp.d(11): Error: none of the overloads of template `std.range.primitives.put` are callable using argument types `!()(int[], int[])` /dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d(386): Candidate is: `put(R, E)(ref R r, E e)` ```d void main() { import std.range : phobos_put = put; enum testLen = 4; auto a = new int[testLen]; auto b = new int[testLen]; auto slice = a[1..$-1]; slice.phobos_put([2, 3]); //a[1..$-1].phobos_put([2, 3]); b[1..$-1].put([2, 3]); import std.conv : text; assert(a == b, text(a)); } void put(R)(R[] range, R[] source) { assert(source.length <= range.length); foreach(element; source) { range[0] = element; // range.front() range = range[1..$]; // range popFront() } } ``` SDB@79
The Phobos put()
Why does my `put` work but the Phobos `put` doesn't work with a slice? onlineapp.d(11): Error: none of the overloads of template `std.range.primitives.put` are callable using argument types `!()(int[], int[])` /dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d(386): Candidate is: `put(R, E)(ref R r, E e)` ```d void main() { import std.range : phobos_put = put; enum testLen = 4; auto a = new int[testLen]; auto b = new int[testLen]; auto slice = a[1..$-1]; slice.phobos_put([2, 3]); //a[1..$-1].phobos_put([2, 3]); b[1..$-1].put([2, 3]); import std.conv : text; assert(a == b, text(a)); } void put(R)(R[] range, R[] source) { assert(source.length <= range.length); foreach(element; source) { range[0] = element; // range.front() range = range[1..$]; // range popFront() } } ``` SDB@79
Re: Step by step tutorials for using bindings in D
On Monday, 27 March 2023 at 00:06:36 UTC, Inkrementator wrote: PS: To really understand what is happening, you might want to try manually compiling a hello world program that depends on a library instead of using dub. Some pointers: `dub build -v` will print out the compiler and linkflags used. `pkg-config --libs --cflags lua` would generate compiler options for you. Use it like `dmd $(pkg-config --libs --cflags lua) program.d` If you decide to try this, I can walk you through it. But remember that it's not that important this is probably all a bit much. Even if I wrote similar articles ([for example](https://forum.dlang.org/post/qnzmxceqesmcsmfmz...@forum.dlang.org), in my own language), it would not be enough! Even writing is not enough... What era are we living in? There is something called YouTube: [How to set up D and GLFW/OpenGL project on MacOS, Linux and Windows](https://www.youtube.com/watch?v=wG6OG6uWyDw=youtu.be) by Ki Rill Likes **17** Views **265** Released on March **8, 2023** I have to ask... How many of you have made such how-to videos? This is a question I have to answer too! Use DUB, recommend, bird in the hand is worth two in the bush SDB@79
Re: Segfault with std.variant
On Saturday, 25 March 2023 at 07:42:28 UTC, Ali Çehreli wrote: This looks like a bug to me. Such a problem does not occur when you set all objects with the new operator. ```d void main() { import std.variant; auto var = Variant([ "one": new Variant(1), "two": new Variant(2), "three": new Variant(3), "four": new Variant(4), "five": new Variant(5) ]); auto six = new Variant(6); var["six"] = new Variant(6); assert(var.length == 6); } ``` SDB@79
Re: Implicit type conversion depending on assignment
On Thursday, 23 March 2023 at 13:38:51 UTC, Alexander Zhirov wrote: ```d struct MyVal { string value; // Here it would be possible to use an alias to this, but it can only be used 1 time } auto a = MyVal("100"); auto b = MyVal("11.2"); int MyInt = a;// Implicitly convert to target type float myFloat = b;// Implicitly convert to target type ``` Have you tried using an associative array? I feel that you will come up with a solution for your purpose from the examples below: ```d template MyContainer(string data = "") { // Container name ---^ struct Var { import std.variant; private Variant[string] values; alias values this; @property { Variant opDispatch(string key)() const { return values[key]; } void opDispatch(string key, T)(T val) { values[key] = val; } } } static if(data.length > 0) { import std.format; mixin(data.format!"Var %s;"); } else { Var data; // no conflicts } } import std.stdio; void main() { enum Tarih { AY = 1, YIL = 2023 } mixin MyContainer!"date"; date.month = cast(ubyte)Tarih.AY; date.month.write("/"); assert(date["month"] != Tarih.AY); assert(date["month"].type == typeid(ubyte)); date.year = cast(short)Tarih.YIL; date.year.writeln(" in Turkish format"); assert(date["year"] != Tarih.YIL); assert(date["year"].type == typeid(short)); writefln("Date: %s/%s", date.year, date.month); } ``` SDB@79
Re: alias Error: need 'this'
On Sunday, 19 March 2023 at 11:52:50 UTC, bomat wrote: It works fine with the `int` variable, but with the struct member I get a compilation error: ``` Error: need `this` for `memberWithALongName` of type `int` ``` What is that supposed to mean? It is possible to achieve the convenience you want to achieve in 2 ways. One of them is to use a static member but if not, to use an alias inside the container. For example: ```d struct MyStruct { int memberWithALongName; alias ln = memberWithALongName; static string str; } void main() { auto myStruct = MyStruct(1); myStruct.ln = 2; alias alias2 = MyStruct.str; alias2 = "2"; import std.conv : text; assert(myStruct.ln.text == alias2); } ``` SDB@79