Re: Why is opIndexAssign replaced by opSlice here?
On Monday, 18 October 2021 at 03:42:35 UTC, Paul Backus wrote: What happens here is, the compiler first tries the D2-style rewrite: ```d s.opIndexAssign(arr[1..4], s.opSlice!0(0, 3)) ``` However, that rewrite fails to compile, because your `opSlice` does not take a template argument specifying the dimension along which to slice, as specified in the language spec's section on ["Slice Operator Overloading".][1] Since the above rewrite fails to compile, it falls back to rewriting the expression using D1-style operator overloads: For backward compatibility, `a[]` and `a[i..j]` can also be overloaded by implementing `opSlice()` with no arguments and `opSlice(i, j)` with two arguments, respectively. This only applies for one-dimensional slicing, and dates from when D did not have full support for multidimensional arrays. This usage of opSlice is discouraged. ...which results in the following rewritten statement: ```d s.opSlice(0, 3) = arr[1..4]; ``` My guess is that you got into this situation by trying to follow the example in the spec's section on ["Slice Assignment Operator Overloading"][2]. Unfortunately, that example is incorrect. Here is a fixed version of your example on run.dlang.io: https://run.dlang.io/is/dtfT5y [1]: https://dlang.org/spec/operatoroverloading.html#slice [2]: https://dlang.org/spec/operatoroverloading.html#slice_assignment_operator Woow! You fixed the problem, it now works for me. I wish the compiler would have been able to make me understand the problem. It was no help because it only tells the final erroneous consequence, that the return value of `opSlice` cannot be assigned ("is no lvalue", beginner-unfriendly language). It doesn't even mention `opSlice` or the fallback (reason) with no warning.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 17:14:30 UTC, Adam Ruppe wrote: On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. This is false. You can use any D features when calling it from C, you just need to provide an init and term function that is called from C that runtime initialize and terminate for the full experience. BetterC helper librarys like Tanya or Tango do exist. I don't know tanya, but Tango has absolutely nothing to do with betterC. It is a set of classes that use the full runtime. That's nice! Do you have a link for more information how to initialize the D runtime? I just wondered about that because I thought it actually shouldn't be much more difficult than just linking the runtime into the foreign-language compiled program. I didn't find information on that. Maybe I didn't search long enough.
Re: Why is opIndexAssign replaced by opSlice here?
Btw, I should have written: `s.opIndexAssign(arr[1..4], s.opSlice(0,3));` But it compiles the same way.
Why is opIndexAssign replaced by opSlice here?
Hello Dear community. I'd like to overload `opIndexAssign` for a struct which wraps around a generic array (so that it can't support `opIndex` due to unknown return type). Broken down as much as possible this is the code: ``` import std.stdio : writeln; import std.range : ElementType; struct S { void opIndexAssign(X, RANGE)(X x, RANGE range) if (is(ElementType!RANGE : size_t)) { writeln(__FUNCTION__); } auto opSlice(size_t start, size_t end) { import std.range : iota; return iota(start, end); } } void main() { auto arr = new int[7]; S s; s.opIndexAssign(arr, s.opSlice(1,4)); // works s[0..3] = arr[1..4]; // does not work, compiles to `s.opSlice(0,3) = arr[1..4]` } ``` I'm clueless about why it wouldn't compile the last statement to `s.opIndexAssign(arr[1..4], s.opSlice(0,3))`. Help appreciated :-)
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote: It would be nice if one could use pattern-matching for it in D. Is this possible? As I know it's impossible, but you can use a regular template: ... If anyone is interested in pattern matching, someone provides a package "dpmatch" which uses PEG (some parsing grammer which is implemented in D) to achieve Haskel-style pattern matching, yet for sum-type definitions only. And they use GC + interfaces. Hence it cannot be used with BetterC. Sumtypes can also be created with the `sumtype` package which uses D's delegate literals for pattern matching.
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote: As I know it's impossible, but you can use a regular template: ```d template isPointedStaticArray(T) { static if (isPointer!T) enum isPointedStaticArray = isStaticArray!(PointerTarget!T); else enum isPointedStaticArray = false; } ``` https://run.dlang.io/is/lR7feP this compiles from 2.086.1 and above That's indeed close to pattern matching and is probably the best answer :-) .
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 15:01:17 UTC, Elmar wrote: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); ``` `isStaticArray` is a good example that makes me ask how to outline an `is()` expression without losing the error catching semantics of the inlined `is()` expression.
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 14:36:50 UTC, Elmar wrote: On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote: You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its length Wow, this is a fine solution. I gonna use it, thank you :-) . Well, I just wondered why your code would compile and mine wouldn't. The `version(all)` variant will not compile on my computer with `rdmd` because `PointerTarget` only allows pointers. But the 2nd one will compile. The `is()` expression catches the compilation error which is nice. This is sufficient: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` It would be nice if one could use pattern-matching for it in D. Is this possible? ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); enum isPointedStaticArray(X : else) = false; ```
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote: You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its length Wow, this is a fine solution. I gonna use it, thank you :-) .
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:56:06 UTC, rempas wrote: Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported Nice :-) , you're right. I need to be more optimistic here. Happy coding.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. Oh well, I could also be wrong with BetterC support of Tanya and Tango but both are alterantives to Phobos.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:10:27 UTC, rempas wrote: Thanks, I'm converting a library from C to D so I have to fix all the other bugs first to see If it's working but probably it will. Have an amazing day my friend! Hopefully it will :-) . D has some good C support. You can call any C function from `D` by declaring it `extern(C) `. The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. In that case it can indeed be better for you to convert the program's entry point into D code. This is unfortunate because it prevents C code bases from using D. There is a tool [C++ Conversion Wizard](https://rainers.github.io/visuald/visuald/CppConversion.html) which could be able to convert C++ and C to D but I don't know how good it is and whether it's usable for free on a GNU/Linux derivative OS. It's only half-automatic.
Re: What is the proper way to outline static-if-conditions ?
PS: the title is a misnomer. `is(T : P*, P) && isStaticArray!P` doesn't either compile when inlined because `P` is not defined when not matched.
What is the proper way to outline static-if-conditions ?
Hey D people. Currently in my project I have worked on a unified type interface for all arrays which requires fixed-size arrays to be stored as pointer (in correspondence to dynamic and associative arrays) and allow them being allocated with any selected allocator. There can be code like this: ```d enum isPointedStaticArray(T) = (is(T : P*, P) && .isStaticArray!P); //... static if (.isPointedStaticArray!T) { // ... } ``` It won't compile when the argument of `isPointedStaticArray()` is NO pointer. The compiler complains, about **`P` being undefined**. What is the best workaround for this? It's crazy. I can reverse the problem that it only fails if the argument IS a pointer: ```d enum isPointedStaticArray(T) = (){ enum condition = `is(`~T.stringof~` : P*, P) && .isStaticArray!P`; static if (__traits(compiles, mixin(condition)) ) return mixin(condition); // "P already defined" error else return false; }(); ``` Types defined in `__traits(compiles, ...)` are emitted to the outside?! Okay, this is my current workaround: ```d enum isPointedStaticArray(T) = (){ static if (is(T : P*, P)) return .isStaticArray!(P); else return false; }(); // ... static if (isPointedStaticArray!T) { } ``` for outlining an expression `is(...) && ...` Is there a simpler way in D to do this? If there only would be a `&&&` short circuit operator which doesn't compile the right side if the left side wouldn't compile to true. Did someone already had the idea of a `static-try-catch` which catches compilation errors?
Re: What is a "comma expression"?
On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote: This is the first time I'm finding something like that. I'm having the following code in C: ``` if (0 == (i >> 7)) { if (len < 1) return -1; v = i; return *ret = v, 1; } ``` This is part of a function that returns an `int`. When I'm running this in C, it works. However in D, I'm getting the following error message: ``` Error: Using the result of a comma expression is not allowed ``` Can someone explain what comma expressions are and why they don't work in D (or if the only doesn't work as returned values from a function)? Hello rempas. The comma-operator `,` is like `;` but results in an expression value, not a statement like `;` would. The left side of `,` is executed like a statement and the value of the right side of `,` is returned. Comma-expressions are merely used to pack additional instructions into places where only expressions are allowed. ```d if (x = y, myNiceFunction(), yay(x), x > 5) { // ... } ``` or ```d if (hasFancyFunkyStuff) x = z, fancy(x), funkyUpdate(z); // too lazy for braces ``` Many consider the `,` operator to be a design-flaw because it makes expressions difficult to read and can be easily abused because the above should actually be: ```d x = y; myNiceFunction(); yay(x); if (x > 5) { // ... } ``` In `D` you can still write the second example of code but not the first example of code. The designers of D thought they could make it less painful by just forbidding comma-expressions to be used as expression value and only as statement. This is because then comma-expressions can still be used in `for`-loops: ```d for (x = y, z = a; x < z; x++, z--) { ; } ``` In conclusion, your C snippet should actually look like: ```c if (0 == (i >> 7)) { if (len < 1) return -1; *ret = v = i; return 1; } ``` The previous snippet even could mislead readers to think that it would return a tuple of two elements which it doesn't.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 10:44:15 UTC, rempas wrote: I'm having the following C code: ``` static void* (*ppmalloc)(size_t) = malloc; static void (*ppfree)(void*) = free; ``` I want to covert this code in D so I try to do the following: ``` static void* function(size_t)*ppmalloc = malloc; static void function(void*)*ppfree = free; ``` If I do that, I'm getting the following error message: ``` Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable using argument types `()` ``` I'm also trying to do the same using "pureMalloc" and "pureFree" instead but this time I'm getting the following error: ``` cannot implicitly convert expression `pureMalloc()(size_t size)` of type `void` to `extern (C) void* function(ulong)*` ``` Any ideas? Hello rempas. This is the way: ```d import core.stdc.stdlib : malloc, free; extern(C) void* function(ulong) mallocPointer = extern(C) void function(void*) freePointer = ``` `function` in the type is already a function pointer. Not immediately obvious though: You also must annotate the type with `extern(C)` otherwise it will not work.
What is the meaning of @future ?
Hello D community. I was browsing the `__traits` keywords and I found `isFuture` whose descriptions says something about `@future`-annotated variables. [link](https://dlang.org/spec/traits.html#isFuture) I didn't find anything about `@future` for the D programming language. I only found that this annotation is used in Apex to denote futures (a.k.a. promises) as programming concept. Is this something which exists, existed, was abandoned early as an idea? I remember I had read that D uses a "fiber" library to provide coroutines and such. Maybe somebody knows an answer for this.
Re: Array permutations
I also should discourage its current form with large `tupleSize`s. The computation is in O(exp(values.length)). Instead of `~=` I would suggest an `std.array.appender` of arrays instead of an 2D-array for the `choices`, if the `choices` become large. Most efficient is a preallocated array capacity. In that case `~=` has very low overhead.
Re: Array permutations
On Saturday, 11 September 2021 at 19:37:42 UTC, Vino wrote: Hi All, Request your help on the below to print the below array as "Required output", Was able to get these values "[1,2],[2,3],[3,4],[4,5]" by using list.slide(2), need your help to get values "1,3],[1,4],[1,5],[2,4],[2,5],[3,5]" auto list[] = [1,2,3,4,5] Required output [1,2],[2,3],[3,4],[4,5],[1,3],[1,4],[1,5],[2,4],[2,5],[3,5] From, Vino Would this be a valid solution to your problem? ```D pure @safe nothrow T[][] computeChoices(T)(T[] values, size_t tupleSize = 2) { if (tupleSize == 0) { return [[]]; } T[][] choices = []; tupleSize--; foreach(i, element; values[0 .. $ - tupleSize]) { import std.algorithm.iteration : map; import std.array : array; choices ~= computeChoices(values[i+1 .. $], tupleSize) .map!(choice => element ~ choice) .array; } return choices; } unittest { assert(computeChoices([1, 2, 3, 4, 5], 2) == [[1,2], [1,3], [1,4], [1,5], [2,3], [2,4], [2,5], [3,4], [3,5], [4,5]] ); } ``` You can choose in the 2nd parameter how large the inner arrays should be. It uses GC to allocate the result via the function `array`. If that is a problem, you could choose an allocator from `std.experimental.allocator` and use the `makeArray` function with the allocator instead of the `array` function. (Manual deallocation could be required then as well.)
Re: Forward references
Hello there, I got a weird compilation error which was hard to debug (even for just a little program) and I thought, this is quite related to this thread. This is my error message: ``` ***search.d(42,1): Error: class ***.XXX has forward references ***box.d(21,32): Error: template instance *** error instantiating ***.d(16,2):instantiated from here: ... ... ``` It was odd, the fix was not obvious and the compiler didn't show me the place of the erroneous forward reference. The problem was a scoped `import` statement!! I had put the import statement for the Box class into the abstract base class Search, the only place where it is used, but this seems to cause a mess with many errors. The imported Box uses a sub class of Search as parameter type and since Search is extended by its subclasses it creates a circular reference in the subclass. The only way to fix was putting the import outside of the abstract base class (I assume because the import statement literally imports the Box together with the used subclass into Search itself). The lesson is, you cannot put your import just everywhere.
Re: Working with ranges
On Saturday, 29 May 2021 at 19:55:30 UTC, Elmar wrote: In many or most of the cases the use case doesn't actually require GC-allocation. Btw, I'm talking about core-level and systems software which concentrates on data transformations. When I only want to access a data structure but not mofify it then GC-allocation would not fit the lifetime logic of a variable. With "modification" I mean the data's size or it's order in memory but not the stored data itself.
Re: Working with ranges
On Wednesday, 26 May 2021 at 15:07:12 UTC, Jack wrote: On Wednesday, 26 May 2021 at 13:58:56 UTC, Elmar wrote: On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe wrote: [...] That's amazing, this should be one thing that should appear in every tutorial just right at the start! I was looking hours for a way to generate an "iterator" (a range) from a fixed-size array which doesn't copy the elements (unless elements are deleted/added). [...] maybe array from std.array to make that range in array of its own? The main incentive here is, that I would like to obtain an iterator (some kind of access view) over a background storage which can be anywhere in memory which I don't care about. It might be on stack frame. In many or most of the cases the use case doesn't actually require GC-allocation. `array()` does GC-allocation and personally, I think `array()` should be avoided whereever the use case doesn't justify GC-allocation, at least if you care for *logically correct* memory management of your program. GC-allocation might just work the same way (most of the time even better than with stack-allocated storage due to design of D) and it adds convenience for you to omit explicit destruction calls which can spare you some conditional checks if the need for destruction depends on runtime cases. But with logical correctness I mean appropriateness here, an allocation scheme which reflects the nature of a variable's lifetime correctly. For example, if the lifetime, maximum storage requirements or the de-/allocation points in code are already known at compile-time then GC-allocation isn't appropriate. It has many drawbacks in performance critical sections, such as non-deterministic destruction time (which probably is the worst), the overhead of scanning GC-allocated regions and the memory fragmentation caused by dynamic allocation (i.e. non-deterministic available storage space) and in the worst case provides additional attack vectors, e.g. with heap overflows or use-after-free. In many cases, it is just better to GC-allocate an entire growable pool or slaps of objects for fast use-case specific allocation. So whatfor I would like to use an iterator? An iterator basically is a meta-data structure which stores meta data (like indices and pointers) for accessing another data structure's contents. And if I just want to change the access of or iteration over a data structure then I don't need to touch how the actual data or memory is stored and I don't even require expensive memory allocation when I could rearrange the iterator contents inplace and if the meta data is much smaller than the actual data. All that is not achieved by `array()`. `array()` is not an iterator but a dynamically allocated copy. Using an iterator like `array[]` saves me expensive GC-allocations. When I only want to access a data structure but not mofify it then GC-allocation would not fit the lifetime logic of a variable. When I understand correctly then the iterator concept in D is called "range". Ranges neither designate a data structure nor a specific data arrangement but it defines a generic access interface of aggregate data whose purpose is to work independent of whatever data structure is accessed via this interface. Now, I'm only missing methods to allocate range iterators on the stack or modifying iterators inplace.
Re: Working with ranges
On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe wrote: On Saturday, 8 December 2018 at 03:48:10 UTC, Murilo wrote: Try passing `ps[]` to the function instead of plain `ps` and see what happens. How do I transform an array into a range? With the slicing operator, []. That's amazing, this should be one thing that should appear in every tutorial just right at the start! I was looking hours for a way to generate an "iterator" (a range) from a fixed-size array which doesn't copy the elements (unless elements are deleted/added). But my issue now is, I have strided arrays (or just any Result range) and I want to use the slicing operator `[]` with that range to copy it into a fixed-size array or apply element-wise operations on it. How can I do that? This example will not compile: ``` auto starts = arr[0..$].stride(2); auto ends = arr[1..$].stride(2); randomNumbers[] = ends[] - starts[]; ``` Because `[]` is not defined for the Result range. Is there a standard wrapper function which wraps an elementwise `[]` operator implementation around a range?