DPP: Linker issue with functions implemented in C header files
Hi, I try to get wrap the "Azure SDK for C" using DPP and have following issue. Functions, which are actually implemented in C header files will cause linker errors: https://github.com/Azure/azure-sdk-for-c/blob/master/sdk/core/core/inc/az_span.h#L91 Example: AZ_NODISCARD AZ_INLINE az_span az_span_init(uint8_t * ptr, int32_t length, int32_t capacity) { return (az_span){ ._internal = { .ptr = ptr, .length = length, .capacity = capacity, }, }; } Error message: /tmp/app.o:az_storage_blobs.d:function _D20blobs_client_example__T19AZ_SPAN_FROM_BUFFERTG4096hZQBdFNbQnZS16az_storage_blobs7az_span: error: undefined reference to 'az_span_init' I do not know C well, is this the expected behavior and should I ask the Azure SDK developers to not implement functions within C header files? Kind regards André
Re: How to get the name of an object's class at compile time?
On Monday, 17 February 2020 at 22:34:31 UTC, Stefan Koch wrote: Upon seeing this I just implemented typeid(stuff).name; https://github.com/dlang/dmd/pull/10796 With any luck this will be possible in the next release ;) Can this work using `stuff.classinfo.name` too ? This is the same as `typeid(stuff).name`
Re: How to get the name of an object's class at compile time?
On Monday, 17 February 2020 at 18:49:55 UTC, Steven Schveighoffer wrote: On 2/17/20 2:28 AM, Nathan S. wrote: What I want is something like this: string className(in Object obj) { return obj is null ? "null" : typeid(obj).name; } ...except I want it to work in CTFE. What is the way to do this in D? https://issues.dlang.org/show_bug.cgi?id=7147 It's not doable. It really should be. -Steve Upon seeing this I just implemented typeid(stuff).name; https://github.com/dlang/dmd/pull/10796 With any luck this will be possible in the next release ;)
Re: Why can't I pass a const array to a function that takes scope const arrays?
On Monday, 17 February 2020 at 20:08:24 UTC, Adnan wrote: On Monday, 17 February 2020 at 14:34:44 UTC, Simen Kjærås wrote: On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote: // All in all, I end up with this code: module strassens_matmul package { T[][] mulIterative(T)(const T[][] mat1, const T[][] mat2) { auto result = createMatrix!T(getRowSize!T(mat1), getColumnSize!T(mat2)); foreach (row; 0 .. mat1.getRowSize()) { foreach (column; 0 .. mat2.getColumnSize()) { T value; foreach (i; 0 .. mat1.getRowSize()) { value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column); } *result.getPointPtr(row, column) = value; } } return result; } } Aren’t these passing by values? That’s why I used ref. Plus since I don’t want to change the arrays in the function scope I used const scope. In D, the type `T[]` is not an array like in C, but a slice, containing a pointer to some data and an integer indicating the array's length. So when you pass it to a function by value, only the pointer and length are copied, not the data itself. You can read more about D's slices in this article: https://dlang.org/articles/d-array-article.html
Re: Why can't I pass a const array to a function that takes scope const arrays?
On Monday, 17 February 2020 at 14:34:44 UTC, Simen Kjærås wrote: On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote: // All in all, I end up with this code: module strassens_matmul package { T[][] mulIterative(T)(const T[][] mat1, const T[][] mat2) { auto result = createMatrix!T(getRowSize!T(mat1), getColumnSize!T(mat2)); foreach (row; 0 .. mat1.getRowSize()) { foreach (column; 0 .. mat2.getColumnSize()) { T value; foreach (i; 0 .. mat1.getRowSize()) { value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column); } *result.getPointPtr(row, column) = value; } } return result; } } Aren’t these passing by values? That’s why I used ref. Plus since I don’t want to change the arrays in the function scope I used const scope.
Re: betterC CTFE nested switch
On Monday, 17 February 2020 at 11:51:03 UTC, Abby wrote: On Monday, 17 February 2020 at 11:05:46 UTC, Stefan Koch wrote: On Monday, 17 February 2020 at 10:18:32 UTC, Abby wrote: [...] I have a ctfe compatible string formatter, you should be to find it here https://forum.dlang.org/post/hmyxvknbdqtlnxvqq...@forum.dlang.org I hope that helps, Regards, Stefan : Hi Stefan, thank you very much for your reply but I could not find the source code or package name anywhere in that forum thread, I was only able to find this https://github.com/UplinkCoder/ctfeutils on github, but it's empty for me. Can you please help and point me to somewhere so I can try it out? Thank you very much Kind regards Abby Sorry I just realized I never published the code. I am going to add it to ctfeutils.
Re: How to get the name of an object's class at compile time?
On 2/17/20 2:28 AM, Nathan S. wrote: What I want is something like this: string className(in Object obj) { return obj is null ? "null" : typeid(obj).name; } ...except I want it to work in CTFE. What is the way to do this in D? https://issues.dlang.org/show_bug.cgi?id=7147 It's not doable. It really should be. -Steve
Re: dub / use git branch
On 2/16/20 9:01 AM, Robert M. Münch wrote: I want to use a specific branch version if a package. I specified the branch version in a dub.selections.json file. But it seems that dub requires a ZIP file that can be downloaded from code.dlang.org, which of course fails because the branch is only available on github. Fetching rtree ~fix-#3 (getting selected version)... Downloading https://code.dlang.org/packages/rtree/~fix-#3.zip failed with 404 (Not Found). How am I supposed to switch to a branch version of a package to try a bug-fix version for example? git clone that branch to a local repository. dub add-local . in that repository. It will say something like "adding v1.0.1+commit..." then you mark your project as requiring ~> v1.0.1, and it will pick your local repository. When you are done, make sure to dub remove-local that repository so it stops trying to grab your local copy. -Steve
Re: Difference between range `save` and copy constructor
> Either way, generic code should never be using a range after > it's been copied, and copying is a key part of how > idiomatic, range-based code works in D. OK. Thanks for instructions. I shall give it a try.
Re: Get compilation errors within opDispatch?
On Monday, 17 February 2020 at 17:01:12 UTC, Adam D. Ruppe wrote: It sometimes helps to write it out log-form foo.opDispatch!"hello"(5); should give the full error. this btw is one of the most annoying missing errors in d... This worked, thank you! On Monday, 17 February 2020 at 16:45:53 UTC, Ali Çehreli wrote: Try dmd command line switch -verrors=spec. Ali This technically also worked, but the error was buried on line 5431 of the 9857-line result.
Re: Get compilation errors within opDispatch?
On Monday, 17 February 2020 at 16:41:54 UTC, cc wrote: Foo foo; foo.hello(5); Result: Error: no property `hello` for type `Foo` It sometimes helps to write it out log-form foo.opDispatch!"hello"(5); should give the full error. this btw is one of the most annoying missing errors in d...
Re: Get compilation errors within opDispatch?
On 2/17/20 8:41 AM, cc wrote: Is there any way to see the compilation errors that occurred within an opDispatch template? struct Foo { void opDispatch(string s, SA...)(SA sargs) { literally anything; } } Foo foo; foo.hello(5); Result: Error: no property `hello` for type `Foo` Desired result: Error: undefined identifier `literally` Try dmd command line switch -verrors=spec. Ali
Get compilation errors within opDispatch?
Is there any way to see the compilation errors that occurred within an opDispatch template? struct Foo { void opDispatch(string s, SA...)(SA sargs) { literally anything; } } Foo foo; foo.hello(5); Result: Error: no property `hello` for type `Foo` Desired result: Error: undefined identifier `literally`
Re: Why can't I pass a const array to a function that takes scope const arrays?
On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote: cdsa ~master: building configuration "cdsa-test-library"... source/strassens_matmul.d(22,16): Error: cannot implicitly convert expression [row][column] of type const(uint)* to uint* source/strassens_matmul.d(37,36): Error: template instance strassens_matmul.getPointPtr!uint error instantiating source/strassens_matmul.d(48,29): I'd just finished writing a long post explaining the stuff you've apparently figured out. Ah well. :p In this case, getPointPtr return T*, but takes scope const ref T[][]. Since getPointPtr always takes a mutable array, you could just get rid of const on its parameters. Alternatively, if you want to be able to use it on arrays of different constness, you could use inout: inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t column) { This will return a pointer to a mutable T if that's what the array holds when you call the function, const(T) if it's a const array, immutable(T) if it's immutable, and so on. The same can be done with the other functions you have. You are also somewhat overusing const, scope and ref, I'd say - you should not take an array by ref unless you plan on modifying it, which you are not doing in getPointPtr or any other of your functions. scope may be worth it, as it guarantees you won't be sending the data elsewhere. None of these are necessary on your ulongs, which are passed by value and never attempted modified. If you really like the extra guarantee that you don't accidentally modify them, feel free to keep 'const', but 'scope' on a ulong does nothing, and it's been argued it should be a compiler error. Lastly, you're using ulongs a lot, and this is mostly correct when compiling for 64-bit, but makes code fail to compile for 32-bit. Using size_t instead makes for code that works for both. All in all, I end up with this code: module strassens_matmul; debug { static import std; } package { size_t getRowSize(T)(const T[][] mat) { return mat[0].length; } size_t getColumnSize(T)(const T[][] mat) { return mat.length; } T[][] createMatrix(T)(size_t rowSize, size_t columnSize) { return new T[][](rowSize, columnSize); } /// row and column are 0 index-based inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t column) { return [row][column]; } T getPointCopy(T)(const T[][] mat, size_t row, size_t column) { return mat[row][column]; } T[][] mulIterative(T)(const T[][] mat1, const T[][] mat2) { auto result = createMatrix!T(getRowSize!T(mat1), getColumnSize!T(mat2)); foreach (row; 0 .. mat1.getRowSize()) { foreach (column; 0 .. mat2.getColumnSize()) { T value; foreach (i; 0 .. mat1.getRowSize()) { value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column); } *result.getPointPtr(row, column) = value; } } return result; } } unittest { const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]]; const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]]; const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35, 33, 45]]; assert(matA.mulIterative(matB) == matC); } -- Simen
Re: Why can't I pass a const array to a function that takes scope const arrays?
On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote: On Monday, 17 February 2020 at 13:44:55 UTC, Adnan wrote: [...] Okay I changed to module strassens_matmul; [...] I changed getPointPtr to following and now it works /// row and column are 0 index-based void assign(T)(ref T[][] mat, ulong row, ulong column, scope const T value) { mat[row][column] = value; }
Re: Why can't I pass a const array to a function that takes scope const arrays?
On Monday, 17 February 2020 at 13:44:55 UTC, Adnan wrote: https://ideone.com/lVi5Uy module strassens_matmul; debug { static import std; } ... Okay I changed to module strassens_matmul; debug { static import std; } package { ulong getRowSize(T)(scope const T[][] mat) { return mat[0].length; } ulong getColumnSize(T)(scope const T[][] mat) { return mat.length; } T[][] createMatrix(T)(scope const ulong rowSize, scope const ulong columnSize) { return new T[][](rowSize, columnSize); } /// row and column are 0 index-based T* getPointPtr(T)(scope const ref T[][] mat, scope const ulong row, scope const ulong column) { return [row][column]; } T getPointCopy(T)(scope const ref T[][] mat, scope const ulong row, scope const ulong column) { return mat[row][column]; } T[][] mulIterative(T)(scope const ref T[][] mat1, scope const T[][] mat2) { auto result = createMatrix!T(getRowSize!T(mat1), getColumnSize!T(mat2)); foreach (row; 0 .. mat1.getRowSize()) { foreach (column; 0 .. mat2.getColumnSize()) { T value; foreach (i; 0 .. mat1.getRowSize()) { value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column); } *result.getPointPtr(row, column) = value; } } return result; } } unittest { const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]]; const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]]; const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35, 33, 45]]; assert(matA.mulIterative(matB) == matC); } /// cdsa ~master: building configuration "cdsa-test-library"... source/strassens_matmul.d(22,16): Error: cannot implicitly convert expression [row][column] of type const(uint)* to uint* source/strassens_matmul.d(37,36): Error: template instance strassens_matmul.getPointPtr!uint error instantiating source/strassens_matmul.d(48,29):
Re: operator overload for sh-like scripting ?
On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote: eg Sh(echo) < "meh"; struct Sh { // you see the idea we have op overload for < here } You can't overload < separately - all the comparison operators (<, <=, >, >=) are handled via opCmp. Even if you choose to go down that route, there are other issues - opCmp needs to return something that may be compared to 0, since (a < b) is rewritten as (a.opCmp(b) < 0), and the compiler checks if you are simply discarding the return value of a comparison, so all in all, you shouldn't do that in D (and the hoops you have to jump through to make it work makes the code a lot less readable): struct Sh { int opCmp(string s) { import std.stdio : writeln; writeln(s); return 0; } } unittest { Sh sh; auto _ = sh < "baz"; } This is also not chainable, so something like (sh < "foo" < "bar") won't work, even with parentheses. There's also the issue of (a < b) having a defined meaning in D (a less than b), and such overloading leads to code that may be less readable. This is a point with differing opinions, and I'm not firmly on either side of that argument, but it's worth pointing out. Now, if you absolutely want something that's somewhat similar in regular D code, there's <<: struct Sh { Sh opBinary(string op : "<<")(string s) { import std.stdio : writeln; writeln(s); return this; } } unittest { Sh sh; sh << "foo" << "bar"; } While this works, it's a design choice that C++ has gotten a lot of flak for, including one of my favorite C++ quotes: "I saw 'cout' being shifted 'Hello world' times to the left and stopped right there." There are cases where it's not at obvious to the reader of the code what's happening, so such operator overloading should be used with caution. A better choice, perhaps, if using < is important, would be to use a DSL and have it obvious in the code that normal D rules aren't at play: void fun() { Sh sh; mixin dsl!` sh < "foo"; `; } At this point though, you're looking at a considerable chunk of code just for a bit of syntactic sugar. -- Simen
Why can't I pass a const array to a function that takes scope const arrays?
https://ideone.com/lVi5Uy module strassens_matmul; debug { static import std; } package { ulong getRowSize(T)(T[][] mat) { return mat[0].length; } ulong getColumnSize(T)(T[][] mat) { return mat.length; } T[][] createMatrix(T)(const ulong rowSize, const ulong columnSize) { return new T[][](rowSize, columnSize); } /// row and column are 0 index-based T* getPointPtr(T)(T[][] mat, const ulong row, const ulong column) { return [row][column]; } T getPointCopy(T)(T[][] mat, const ulong row, const ulong column) { return mat[row][column]; } T[][] mulIterative(T)(scope const T[][] mat1, scope const T[][] mat2) { auto result = createMatrix!T(mat1.getRowSize, mat2.getColumnSize); foreach (row; 0 .. mat1.getRowSize()) { foreach (column; 0 .. mat2.getColumnSize()) { T value; foreach (i; 0 .. mat1.getRowSize()) { value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column); } *result.getPointPtr(row, column) = value; } } return result; } } unittest { const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]]; const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]]; const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35, 33, 45]]; assert(matA.mulIterative(matB) == matC); } /// source/strassens_matmul.d(30,42): Error: template strassens_matmul.getRowSize cannot deduce function from argument types !()(const(uint[][])), candidates are: source/strassens_matmul.d(8,11):getRowSize(T)(T[][] mat) source/strassens_matmul.d(30,59): Error: template strassens_matmul.getColumnSize cannot deduce function from argument types !()(const(uint[][])), candidates are: source/strassens_matmul.d(12,11):getColumnSize(T)(T[][] mat) source/strassens_matmul.d(31,43): Error: template strassens_matmul.getRowSize cannot deduce function from argument types !()(const(uint[][])), candidates are: source/strassens_matmul.d(8,11):getRowSize(T)(T[][] mat) source/strassens_matmul.d(48,29): Error: template instance strassens_matmul.mulIterative!uint error instantiating dmd failed with exit code 1.
Re: operator overload for sh-like scripting ?
On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote: Sh(echo) < "meh"; Not allowed in D - it only does a comparison overload which covers < and > (and <= and >=). Though we could do strings and stuff. especially with my string interpolation dip https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f we could make it work quite well!
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 12:11:38 UTC, Simen Kjærås wrote: On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature wrote: [...] One tiny thing: the above fails for tuples with named fields, like Tuple!(int, "a", string "b"). This code handles that case, and preserves field names: [...] Thank you all
operator overload for sh-like scripting ?
eg Sh(echo) < "meh"; struct Sh { // you see the idea we have op overload for < here }
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature wrote: Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); } One tiny thing: the above fails for tuples with named fields, like Tuple!(int, "a", string "b"). This code handles that case, and preserves field names: import std.meta : staticMap, aliasSeqOf; import std.typecons : Tuple; import std.range : array, iota; import std.algorithm : map; alias ToArray(T) = T[]; alias ToArray(T...) = T; alias ToArrayTuple(T : Tuple!U, U...) = Tuple!(staticMap!(ToArray, U)); auto transpose(T : Tuple!U, U...)(T[] arr) { auto extract(int i)() { return arr.map!(a => a[i]).array; } return ToArrayTuple!T(staticMap!(extract, aliasSeqOf!(T.Types.length.iota))); } unittest { alias T = Tuple!(int, "a", string, "b"); auto a = [T(1, "a"), T(2, "b")]; assert(a.transpose.a == [1, 2]); assert(a.transpose.b == ["a", "b"]); } -- Simen
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote: Hi all, There's something in Phobos for that? Thank you Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); }
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature wrote: On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote: Hi all, There's something in Phobos for that? Thank you Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); } ^^ Do what he said - I misread the title. :) -- Simen
Re: betterC CTFE nested switch
On Monday, 17 February 2020 at 11:05:46 UTC, Stefan Koch wrote: On Monday, 17 February 2020 at 10:18:32 UTC, Abby wrote: Hi there guys, I was trying to generated code during compile time. Bassicly I'm creating a tokenizer and I would like to generated nested switch using betterC. [...] I have a ctfe compatible string formatter, you should be to find it here https://forum.dlang.org/post/hmyxvknbdqtlnxvqq...@forum.dlang.org I hope that helps, Regards, Stefan : Hi Stefan, thank you very much for your reply but I could not find the source code or package name anywhere in that forum thread, I was only able to find this https://github.com/UplinkCoder/ctfeutils on github, but it's empty for me. Can you please help and point me to somewhere so I can try it out? Thank you very much Kind regards Abby
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote: Hi all, There's something in Phobos for that? Thank you import std.meta : staticMap; import std.typecons : Tuple; // Turn types into arrays alias ToArray(T) = T[]; // Leave everything else the same alias ToArray(T...) = T; // Now apply the above to each element of the Tuple template args: alias ToArrayTuple(T : Tuple!U, U...) = Tuple!(staticMap!(ToArray, U)); unittest { alias A = Tuple!(int, string); assert(is(ToArrayTuple!A == Tuple!(int[], string[]))); alias B = Tuple!(int, "a", string, "b"); assert(is(ToArrayTuple!B == Tuple!(int[], "a", string[], "b"))); } -- Simen
From [Tuple!(A,B), ...] to Tuple!(A[], B[])
Hi all, There's something in Phobos for that? Thank you
Re: betterC CTFE nested switch
On Monday, 17 February 2020 at 10:18:32 UTC, Abby wrote: Hi there guys, I was trying to generated code during compile time. Bassicly I'm creating a tokenizer and I would like to generated nested switch using betterC. [...] I have a ctfe compatible string formatter, you should be to find it here https://forum.dlang.org/post/hmyxvknbdqtlnxvqq...@forum.dlang.org I hope that helps, Regards, Stefan :
betterC CTFE nested switch
Hi there guys, I was trying to generated code during compile time. Bassicly I'm creating a tokenizer and I would like to generated nested switch using betterC. Basically convert something like this: enum tokens = [ ['!', '='], ['>', '='], ['>'], ]; to: switch(str[i]) { case '!': switch(str[i + 1]) { case '=': onToken(['!', '=']); break; default: break; } break; case '>': switch(str[i + 1]) { case '=': onToken(['>', '=']); break; default: onToken(['>']); break; } break; default: break; } but right now I'm stuck and I don't know how to achieve this. I was able to find out that: 1) Switches has to be labeled and the only way I know how to do so is to use string code and then mixing it. I was hoping for example to mixing only labels before switch and after continue and break but this does not seem to work :/ 2) Format does not work in compile time using betterC (sprintf also does not work Thank you very much for any kind if help Kind regards Abby
Re: How to iterate over range two items at a time
On Monday, 17 February 2020 at 09:41:35 UTC, Adnan wrote: On Monday, 17 February 2020 at 07:50:02 UTC, Mitacha wrote: On Monday, 17 February 2020 at 05:04:02 UTC, Adnan wrote: What is the equivalent of Rust's chunks_exact()[1] method in D? I want to iterate over a spitted string two chunks at a time. [1] https://doc.rust-lang.org/beta/std/primitive.slice.html#method.chunks_exact It sounds similar to `slide` https://dlang.org/phobos/std_range.html#slide The key difference here is that slide seems to overlap, which is a big no-no for my current problem. I have just gone with a classic for loop. Error prone, but just works. Yeah your analysis is right. slide is specifically made to overlapp, if overlapping is not needed slide is not needed.
Re: How to iterate over range two items at a time
On Monday, 17 February 2020 at 07:50:02 UTC, Mitacha wrote: On Monday, 17 February 2020 at 05:04:02 UTC, Adnan wrote: What is the equivalent of Rust's chunks_exact()[1] method in D? I want to iterate over a spitted string two chunks at a time. [1] https://doc.rust-lang.org/beta/std/primitive.slice.html#method.chunks_exact It sounds similar to `slide` https://dlang.org/phobos/std_range.html#slide The key difference here is that slide seems to overlap, which is a big no-no for my current problem. I have just gone with a classic for loop. Error prone, but just works.
best practices for a new project
When I start a new project is there anything that I should get right from the start? Like using a specific set of compiler flags (e.g. -dip1000)? Is there an overview over the status of upcoming language changes (-preview=?), e.g. what about -preview=rvaluerefparam? Should I use it?