Re: byte + byte = int: why?
On Friday, 18 January 2019 at 18:49:23 UTC, Steven Schveighoffer wrote: As others have said, those are the rules D has for historical reasons, you just have to deal with them. Is that to ensure compatibility with C?
Re: Non-consistent implicit function template specializations
On Wednesday, 18 August 2021 at 13:35:07 UTC, Paul Backus wrote: On Wednesday, 18 August 2021 at 11:10:49 UTC, Rekel wrote: I tried looking into how isArray is defined. Like, does being able to index mean it's an array, or are these only static &/or dynamic arrays? Did you read the documentation? https://phobos.dpldocs.info/std.traits.isArray.html Ah it's specifically static & dynamic arrays, I see.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 18:46:05 UTC, Ali Çehreli wrote: I don't have such problems because I am not smart enough to understand that syntax so I don't use it. :) I use template constraints (which have other problems). Yeah, they seem to be a bit more trustworthy to some extent. If you want 2 dimensional arrays, then you can use import std.range; isArray!T && (isArray!(ElementType!T)) I tried looking into how isArray is defined. Like, does being able to index mean it's an array, or are these only static &/or dynamic arrays? Though I couldn't understand the sourcecode. Hence I just use(d) `is(typeof(variable[0]))` and `is(typeof(variable[0][0]))`.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 18:27:21 UTC, Steven Schveighoffer wrote: According to my tests, it prefers the `T` version over the static array version. Which leads me to believe that it prefers a dynamic array over a static one. In fact, if I comment out the `T` version, it doesn't compile. It literally will not pick that specialization, even if it can interpret the literal that way. which is really bizarre, since if you do it without specializations, but just spelling out all the template components (as in your alternative workaround), it WILL pick that one over a dynamic array one. Oh my, that's weird... Not meant to bash but given all I've seen of argument deduction & templates & specializations... I think the implementation needs some serious rework 😅 --- Interestingly enough my approach will not even work for 2d array literals. It will manage going to int[][2], but int[2][2] is one step too far. Which is a real bummer. :( That is, it won't figure it out itself, but when you call `foo(T, uintL)(T[L][L]...` using an explicit `foo!(int, 2)` it _will_ work. Even though it manages T[L] just fine. Meanwhile T[2][L] _and_ T[L][2] won't work when called with a 2x2 array literal.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 16:24:38 UTC, Steven Schveighoffer wrote: void foo(T:U[L], uint L)(T a){...} This is an invalid specification, what is U? Did you mean: Yes, sorry typo in the forum. void foo(T: U[L], U, uint L)(T a) {...} void foo(T:U[L][L], uint L)(T a){...} // Never matched Apart from another missing U, this is only a SQUARE 2d-array (both dimensions the same), your example below only calls with a 1x2 array. Again, sorry a typo, calling with `[[1,2],[3,4]]`. void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched (alternatively) I don't think you need this, and I had to comment it out, or the compiler wouldn't build. That is correct, it's equivalent thus causes 2 matches. All these are calling with array literals, which default to dynamic arrays, not static arrays. I realise that is their default, though in this scenario they should (I believe) be used as static arrays. (This works for me in any case)
Re: Anyway to achieve the following
On Saturday, 14 August 2021 at 20:50:47 UTC, Carl Sturtivant wrote: ``` struct S { int x = 1234; } void main() { import std.stdio; S s; //construction of a using &(s.x) auto a = Ref!(int)(&s.x); writeln(a); //displays 1234 s.x += 1; writeln(a); //displays 1235 a += 1; writeln(s.x); //displays 1236 } struct Ref(T) { T* ptr; this(T* p) { ptr = p; } string toString() { import std.conv; return to!string(*ptr); } ref T var() { return *ptr; } alias var this; } ``` Wow you can alias this a function? TIL!
Re: Non-consistent implicit function template specializations
As my post was not the actual cause of my issue (my apology for the mistake), I think I have found the actual reason I'm currently having problems. This seems to be related to a (seeming, I might be wrong) inability to specialize over both 1d and 2d arrays separately. (If constraining the length to values.) This brings me to 2 questions. 1. How does one specialize a template for both 1d and 2d arrays at the same time? 2. Are there any plans to rework templates? like: - Making `template TFoo(T : T[])` illegal. This makes little sense to me however I look at it, and as several people have advised against it it's confusing it's in the docs. (21.4.1) - Changing the way priorities are set using specializations in general, to make them less pitfall-y. - Allow for 2+d length specification. At the moment `T[][L]` works while `T[L][L]` does not seem to. ```d void foo(T)(T a){...} void foo(T:U[L], uint L)(T a){...} void foo(T:U[L][L], uint L)(T a){...} // Never matched void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched (alternatively) // Alternative workaround, very cluttery but with more control. void foo(T)(T a) if(!is(typeof(a[0]))&&!is(typeof(a[0][0]))) {...} void foo(T, uint L)(T[L] a) if(!is(typeof(a[0]))){...} void foo(T, uint L)(T[L][L] a) {...} // Still does not work. void foo(T, unit L(T[][L] a) {static foreach(i;0..L) assert(a[i].length==L); ...} // Will (generally) work but may include runtime checking & is generally much less preferrable. // Should work with void main(string[] args) { foo([[1],[2]]); foo([1,2]); foo(1); } ``` - Supporting specializations such as the following (from https://forum.dlang.org/post/kdgfwlydkgmwvzrie...@forum.dlang.org): ```d void foo(L, T, uint S)(L l, T[S] r){ writeln("foo"); } void bar(L, R:T[S], T, uint S)(L l, R r){ writeln("bar"); } void main(string[] args) { foo(1, [1,2,3,4]); // "foo" bar(1, [1,2,3,4]); // "cannot deduce function" } ``` I'm actually still not sure why this shouldn't work, but changing bar to foo isn't too difficult. (though it's more preferrable to work regardless, it currently feels like a pitfall) --- Not sure if I'm asking the right questions, hope it's not of nuisance. - Rekel
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 10:21:39 UTC, Mike Parker wrote: We do have a paid Issue/Pull-Request manager now (Razvan Nitu), and he's prioritizing issues for strike teams composed of volunteers willing to fix them. If you find a specific bug that is a blocker or a major headache, make a post about it here in the forums. Sometimes, the reason a bug hasn't been fixed is simply that it hasn't caught the attention of the right person. With Razvan in place, it's more likely such issues will be resolved, or at least moved up on the priority list, if you let him know about them. A forum post is an easy way to do that while also bringing it to the attention of others who may be looking for something to work on. That's great to hear :), I'll keep it in mind.
Re: Non-consistent implicit function template specializations
On Tuesday, 17 August 2021 at 10:14:07 UTC, Mike Parker wrote: The error is in your code. Both of your `foo` templates are implemented to print `"1"`. Change the second one to print "2" and you will see the desired output. I keep managing to disappoint myself greatly... this is absurd, so sorry.
Non-consistent implicit function template specializations
When using implicit function templates, identical specialization yield different results. Example: ```d template TFoo(T){ void foo(){writeln("1");} } // #1 template TFoo(T : T[]) { void foo(){writeln("2");} } // #2 void foo(T)(){ writeln("1"); } void foo(T : T[])(){ writeln("1"); } void main(string[] args) { // Works TFoo!(int).foo();// "1" TFoo!(double[]).foo(); // "2" foo!(int)();// "1" foo!(double[])(); // "1" ! } ``` I'm fairly certain the last call _should_ yield "2", yet it does not. Should I submit a bugreport? And will that even help? There's even 'NEW' bugs from 2016 :'c --- Interestingly enough, it seems I've made a previous thread about this in January (https://forum.dlang.org/post/zudtiruaxdfdwcjen...@forum.dlang.org), though in it I state `TFoo!(uint[]) yields the array version`, which as can be seen from the example above, is not or no longer true. Sadly I'm having issues with template arguments more often (https://forum.dlang.org/post/xkgpheuhohbffzgdb...@forum.dlang.org) And I sadly don't see any improvement to this happening any time in the future. Even bugs don't seem to get fixed in any timely manner (Not meant as an insult, just being realistic :/).
Re: Nondeterministic unittest debugging problem.
On Monday, 16 August 2021 at 22:01:21 UTC, russhy wrote: remove the .dub folder and try again, as stated in other reply, might be a cache issue, or something that picks an outdated file in the cache Thanks, I'll try that, sadly clear didn't seem to fix it.
Re: Nondeterministic unittest debugging problem.
Note you might need to open the screenshots externally, as they are cut off by the forum.
Nondeterministic unittest debugging problem.
I am unsure where to mention this as I am utterly lost as to what the issue is, which I can simply best describe with 2 screenshots. Though I'll first give a short description. For some reason my debugger is "\" for one of my variables in one of my unittests. This is however not the case when a random unused variable is inserted in front of it. (For reference I'm building the unittest using something similar to `dub build --build=unittest --config=unittest --force --archType=x86_64`, though the project is a library thus there are some complications: https://github.com/dlang/dub/issues/1856#issuecomment-899022431) Not readable: ![](https://www.dropbox.com/s/j6bt3gaxu05om2j/Fout.png?dl=0&raw=1) Readable: ![](https://www.dropbox.com/s/lnj3ugmuoh339oi/Fout2.png?dl=0&raw=1) ```d int x = 0; Mat!(3, 3, float) a = Mat!(3, 3, float)([1, 2, 3, 4, 5, 6, 7, 8, 9]); ``` Note the x variable is entirely unused while Mat is a struct of a union that is essentially just a 2d array of floats. I have no more clue where to look as I have no clue what could cause this, am I overlooking something trivial? Thanks in advance.
Re: Anyway to achieve the following
On Friday, 13 August 2021 at 09:10:18 UTC, Tejas wrote: On Friday, 13 August 2021 at 08:25:33 UTC, JG wrote: Suppose one has a pointer p of type T*. Can on declare variable a of type T which is stored in the location pointed to by p? Umm is this what you want? ```d import std.stdio; struct S { int x = 1234; } void main() { S s; /*(ref a){ writeln(a); s.x = s.x + 1; writeln(a); a = a +1; writeln(s.x); }(s.x);*/ auto a = &(s.x); writeln(*a); s.x += 1; writeln(*a); *a += 1; writeln(s.x); } ``` That's also what I thought, although at first I thought JG meant dereferencing a pointer to a type without reallocating the content. In a way comparable to aliasing A* or having your original data be a union in the first place. It seems however one can use `.` when using pointers, which is cool, though there seem to be some caveats: https://forum.dlang.org/post/hthxvxxsxdpkvwcwg...@forum.dlang.org (note this is 2014...)) For anyone more experienced with C, I'm not well known with references but are those semantically similar to the idea of using a type at a predefined location? Small sidenote, this would be cool: ```d int* ip = cast(int*)other_pointer; int a = #a; // like a dereference but without allocating space for a elsewhere. int b = #a; // Or something along those lines a = 1; b += 1; assert(a==2); ```
Building a unittest executable for a dub Library
I found a this thread about testing libraries: https://forum.dlang.org/post/mailman.1807.1522279261.3374.digitalmars-d-le...@puremagic.com But it's very old, yet I have the same issue today. I want to build a unittest executable for the library I've made, but given I'm trying to use the vscode debugger while using the build command in a preLaunchTask I can't just use dub test. This works fine for non-libraries. After changing my targetType from 'dynamicLibrary' to automatic I no longer get the error, but now it's just compiling the .lib file. I also tried adding an empty main but that just makes using it as it's supposed to more obfuscated.
Re: Is returning void functions inside void functions a feature or an artifact?
On Tuesday, 3 August 2021 at 00:53:43 UTC, user1234 wrote: You got the answer in another reply but here is a bit of more fun: ```d void main() { return cast(void) 1; } ``` What does casting to void do? Does it just ignore whatever follows it? On Tuesday, 3 August 2021 at 07:23:34 UTC, Patrick Schluter wrote: Wow. Just discovered that C accepts it. After 35 years of daily use of C, there are still things to discover. Hehe, glad to hear I'm not the only one. Feel like making a request to add this to the learning pages now "x3
Re: Is returning void functions inside void functions a feature or an artifact?
On Monday, 2 August 2021 at 14:51:07 UTC, H. S. Teoh wrote: This is intentional, in order to make it easier to write generic code without always having to special-case functions that don't return anything. Ooh that indeed seems useful. Thanks for the hint. Also slightly off topic, but when would one use an alias instead of a function/delegate? I haven't used aliases before.
Re: Is returning void functions inside void functions a feature or an artifact?
On Monday, 2 August 2021 at 14:46:36 UTC, jfondren wrote: C, C++, Rust, and Zig are all fine with this. Nim doesn't like it. I had no clue, never seen it used in any case. I've always assumed one couldn't return void as it's not a value. I guess intuitions aren't always universal 😅. Good to know c is fine with this too! ^^
Is returning void functions inside void functions a feature or an artifact?
I recently found one can return function calls to void functions, though I don't remember any documentation mentioning this even though it doesn't seem trivial. ```d void print(){ writeln("0"); } void doSomething(int a){ if (a==0) return print(); writeln("1"); } void main(string[] args) { doSomething(0); // Prints 0 but not 1. } ``` If this is intended, where could I find this in the docs? I haven't been able to find previous mentions on this, neither on the forum.
Re: Cannot always deduce template arguments when using implicitly cast array literals
On Friday, 23 July 2021 at 14:41:41 UTC, Paul Backus wrote: The first is to change the type of right from const R to const T[L1], which removes the type specialization: Thanks for suggesting that fix, removing R altogether is a very simple solution I hadn't considered. :) Unfortunately, the algorithm it uses for this is not very sophisticated, and does not take type specializations (like `R : T[L1]`) into account. This seems like a slight oversight to me, do you know if there would be any chance of this changing in the future?
Cannot always deduce template arguments when using implicitly cast array literals
After simplifying a part of my code I found the following code cannot deduce the template arguments, but I have no clue why. ```d void foo(L : T[L1][L2], uint L1, uint L2, T, R: T[L1])(const L left, const R right) { // Function } void bar(uint L)(float[L] l) { // Function } void main(string[] args) { foo2([1.0f, 2, 3, 4, 5, 6, 7, 8]); // implicitly cast to float[8], works float[4][1] l = [[1, 2, 3, 4]]; foo!(typeof(l), 4, 1, float, float[4])(l, [1.0f, 2, 3, 4]); // also works foo(l, [1.0f, 2, 3, 4]); // cannot deduce function from argument types (?) } ``` As one can see, implicitly casting array literals in templates works fine in the case of bar, as does explicit use of templates in the case of foo, but for some reason foo does not manage to deduce its arguments like bar does. The type of l is well known, and given the template, the type of R should thus be known as well. T[L1] should be deduced to float[4]. Did I make a mistake in the argument list? I know things like the order are sometimes issues, but that seems fine to me here. Seeing as bar functions fine (as does foo when R and right are removed) I'm at a loss. Thanks you in advance!
Re: Getting resulting/return type from operation in templates
On Tuesday, 6 July 2021 at 15:00:24 UTC, Paul Backus wrote: On Tuesday, 6 July 2021 at 14:43:26 UTC, Rekel wrote: Is there any reason the function call in the alias is acceptable? I would imagine the () part would actually require 2 parameters. You're right, it does; that was a mistake on my part. It should work with `Lhs.init` and `Rhs.init` as arguments. Hmm . . . doing that ironically brings me back to using: ```d alias ResultType(Lhs, string op, Rhs) = typeof(mixin("Lhs.init" ~ op ~ "Rhs.init")); auto opBinary(string op, R: T2[], T2)(R right) const if (is(ResultType!(T, op, T2))) { Vec!(ResultType!(T, op, T2), L) result; static foreach (i; 0 .. L) { mixin("result[i] = this[i] " ~ op ~ " right[i];"); } return result; } ``` Kind of ironic this is basically an alias of my old solution. Strangely enough the nanF issue went away though, I guess I misinterpreted this. Thanks for your help anyway 😅
Re: Getting resulting/return type from operation in templates
On Tuesday, 6 July 2021 at 14:27:35 UTC, Paul Backus wrote: Instead of having the template evaluate to a `bool`, have it evaluate to the type of the result: ```d alias ResultType(Lhs, string op, Rhs) = typeof(((Lhs lhs, Rhs rhs) => mixin("lhs", op, "rhs"))()); static assert(is(ResultType!(int, "+", double) == double)); static assert(is(ResultType!(string, "~", string) == string)); static assert(!is(ResultType!(string, "+", int))); // no valid result type ``` Then you can use `is()` in the template constraints to check whether the operation is supported: ```d auto opBinary(string op, Rhs: T2[], T2) const if (is(ResultType!(T, op, T2))) { Vec!(ResultType!(T, op, T2), L) result; // etc. } ``` Oh that's neat, thanks. I guess that would make it: ```d auto opBinary(string op, R)(R right) const if (is(ResultType!(T, op, R))) { Vec!(ResultType!(T, op, R), L) result; static foreach (i; 0 .. L) { mixin("result[i] = this[i] " ~ op ~ " right;"); } return result; } ``` I guess I'll just have to take the result definition for what it is. At least the return type can use auto, haha. Imagine using ResultType!(T, op, R) thrice... Is there any reason the function call in the alias is acceptable? I would imagine the () part would actually require 2 parameters.
Getting resulting/return type from operation in templates
I recently found __traits(compiles, ...) can be used in template constraints. (I first used `is(mixin("T.init"~op~"T2.init"))` but this cause problems related to nanF) However I'm wondering if there is an easier way to do what I'm currently doing, especially since using typeof inside the result declaration is quite cumbersome. This is a bigger problem in my less-simplified code (using matrices), where it starts getting slightly unreadable. It also assumes the presence of .vec[0] (not necessarily a problem here but it seems like a codesmell) Simplified: ```d template supported(A, string op, B) { const bool supported = __traits(compiles, (A a, B b) { mixin("return a" ~ op ~ "b;"); }); } struct Vec(T, uint L) { T[L] vec; alias vec this; auto opBinary(string op, R: T2[], T2)(R right) const if (supported!(T, op, T2)) { Vec!(typeof(mixin("this[0]" ~ op ~ "right[0]")), L) result; static foreach (i; 0 .. L) { mixin("result[i] = this[i] " ~ op ~ " right[i];"); } return result; } auto opBinary(string op, R)(R right) const if (supported!(T, op, R)) { Vec!(typeof(mixin("this[0]" ~ op ~ "right")), L) result; static foreach (i; 0 .. L) { mixin("result[i] = this[i] " ~ op ~ " right;"); } return result; } } void main(string[] args) { Vec!(float, 4) v = Vec!(float, 4)([0, 1, 2, 3]); auto w = v * 2.0; auto x = v + v; auto y = v + [1, 1, 1, 1]; pragma(msg, typeof(w)); // prints "Vec!(double, 4u)" pragma(msg, typeof(x)); // prints "Vec!(float, 4u)" pragma(msg, typeof(y)); // prints "Vec!(float, 4u)" } ```
Re: Remove array element within function
Oh my, thank you both, that mostly cleared up my confusion, I had no clue this was struct related. I'll be reading the references you gave me & probably submitting an issue 👍
Re: Remove array element within function
On Monday, 5 July 2021 at 14:22:24 UTC, jfondren wrote: What use of long? remove returns the same type of range as it gets: My apology, I meant to say countUntil instead of remove in that context.
Re: Remove array element within function
I'm not sure if this is the place to talk about it, but on the same topic it's a little strange to me neither the Dlang Tour nor the arrays spec page mention removing elements. Even though basically everyone is going to use it sooner or later (most likely sooner). Is that because it's part of the library? That's the only reason I could think of, while in a way I could make that argument for appending in the case it hadn't been given the `~` and `~=` operators.
Re: Remove array element within function
Ah, ref, thanks, I didn't know if that would work as I was confused since arrays themselves are kind of already pointers. On Monday, 5 July 2021 at 13:18:55 UTC, Mike Parker wrote: In what situations do you need to manually change the length? Where do you worry about copies? It's possible there's something you're overlooking. I believe for setting length it was both when I wanted to initialize the array to a certain length (instead of having that inline with the declaration) & when I want to clear the array of all data. Though I also found threads in which people mentioned changing the length manually after calling remove. The copies were mostly at play in scenarios such as this one, but also when I'm appending lists to lists, in a `list.addAll(list2);` scenario. Though I guess I'm just not used to reassigning on the list variable after doing things with it. Also, is my use of long correct? The documentation wasn't very clear on the return type of remove, just calling it a 'number'. Again thanks for your help 😅
Remove array element within function
Is there an easy way to remove elements from an array passed in as a parameter? Every example I find does something along the lines of: ```d int[] a = ... long index = countUntil(a, element); a = a.remove(index); But what do you do when you have?: ```d void function(int[] a){ . . . long index = countUntil(a, element); a.remove(index); } ``` I assume I can't use a=a.remove(index), as I'm guessing this will only change the array inside the function itself, not the array that's actually used to call the function. Am I the only one slightly unamused by how arrays/ranges work? They keep backfiring on me, or require weird additions other languages wouldn't require such as manually changing .length, or worrying about what operation returns a copy etc. (Kind of jealous of java's ease here)
Re: CTFE Assignment to anonymous union shows unexpected behavior
On Friday, 23 April 2021 at 00:55:50 UTC, H. S. Teoh wrote: [...] If you read the field during CTFE. I've never tested initializing a union in CTFE then reading it at runtime, though. Not sure exactly what would happen in that case. T I'm not referring to reading non-initial variables, though Im surprised that's not possible? In any case, it seems assigning values doesn't work during CTFE either ... And that is very disappointing to me to be quite honest... This only seems to happen when I use CTFE to create a static singleton of the union by assigning to non-initial variables, I couldn't find anything in the docs that say I shouldn't, I might have missed something... I really hope this is a bug... if its not, & assuming its not inevitable, this really shouldn't be a thing. Be it by design or limitation.
Re: CTFE Assignment to anonymous union shows unexpected behavior
On Thursday, 22 April 2021 at 23:41:33 UTC, H. S. Teoh wrote: On Thu, Apr 22, 2021 at 10:47:17PM +, Rekel via Digitalmars-d-learn wrote: I'm not sure why this is happening, but after simplifying my code I traced it back to what the title may suggest. Keep in mind that CTFE does not support reinterpretation via unions, i.e., reading values from a different field in a union than was assigned. If you assign field A to a union, then you cannot read field B from that union in CTFE. You can only do this at runtime, not in CTFE. T I'm not sure what you mean, do you mean if i were to read the field during CTFE, or even if i read the field during runtime after initializing it using CTFE?
CTFE Assignment to anonymous union shows unexpected behavior
I'm not sure why this is happening, but after simplifying my code I traced it back to what the title may suggest. The original cause of my issues being summarized by debug print statements returning a union as: Mat([nanf, nanF, . . . .], [[1.0F, 0.0F, . . . .]) Even though the nanF should thus be 1.0, 0.0, etc... This is example code that describes when this happens: ```d import std.stdio; struct Apple(uint size) { union { int[size * size] a; int[size][size] b; } static immutable typeof(this) pie = _pie(); private static typeof(this) _pie() pure { typeof(this) result; static foreach (i; 0 .. size) static foreach (j; 0 .. size) //result.a[i + j * size] = 1; // Works result.b[i][j] = 1; // Fails return result; } } void main() { Apple!(4) a = Apple!(4).pie; writeln(a.a); writeln(a.b); } ``` The working code changes the first integers to 1, the failing version keeps them at 0. What's the reason for this? Logically this doesn't seem troublesome to me, and if assigning to non-initial anonymous union varialbes isn't possible(?!) that would be pretty bad, and I'd be in for quite some trouble in my actual code :(
Tuple enumeration without integers or strings
I seem to have hit a bit of a wall when comparing D enums to Java enums. Of course the latter is just a fancy class, though it'd be nice to see partially equivalent usefulness regardless. For example, as soon as non-integer, non-string values are given to enums things get messy for me when using switch cases, I haven't yet found a satisfying way of doing this. Note the reason I'm using tuples is to somehow replicate the way java enumerals can contain several member variables, which tends to be very useful. Something along the lines of the following is what i'd like to achieve; alias Direction = Tuple!(byte, "x", byte, "y"); enum Wind {N = Direction(0, 1) ... etc} ... void some_function(Wind w) { switch (w) { case Wind.N: ... etc break; ... etc default: assert(0); } } One thing that might have worked would have been an equivalent of java's "ordinal", though from what I've found D doesn't seem to have something equivalent to this? (I'd prefer not to have a seperate tuple member purely for ordinality, and dropping enumerals altogether also seems like a waste)
Re: Custom type / Typle type formatted reader
And regarding the rest, I'm curious about reading back user types, without defining a new seperate method for it, such as structs, unions and tuples, (although I'm unsure to what extent tuples are really a user-defined-type). The other thing just resolved itself; I was wondering, as slurp kind of already reads tuples from files, whether or not it's possible to tell it what tuple you want it to read, instead of redefining a possibly previously aliased tuple. It seems now I found a way to do just that . . . I honestly don't know why this went wrong before, must have made a mistake somewhere. This now works: alias Entry = Tuple!(int, "a", char, "b"); Entry[] results = slurp!Entry("temp.txt", "%s %s"); results.writeln; Im actually kind of surprised it does, as nothing in the documentation seems to hint to me this makes sense, neither did I find any example like it elsewhere.
Re: Custom type / Typle type formatted reader
On Thursday, 31 December 2020 at 18:19:54 UTC, Ali Çehreli wrote: Can you describe it with a piece of code? If the code shows what the current undesired output is and what you want instead, perhaps we can find a solution. Regarding the enum part; While trying to do this I noticed one cannot use either slurp or formattedRead to read enums, while it is possible to use formattedWrite and write to write them. Strangely enough this was also mentioned in old issue '18051' (https://forum.dlang.org/thread/mailman.735.1512835762.9493.digitalmars-d-b...@puremagic.com) which should have been resolved. Example code; ``` import std.stdio; import std.file : slurp; import std.format; import std.typecons; enum Thing { A, B } void main() { File file = File("temp.txt", "r"); foreach (line; file.byLine) { int integer; Thing thing; formattedRead!"%s %s"(line, integer, thing); // crashes with thing as Thing, works with thing as char. formattedWrite(stdout.lockingTextWriter, "%s %s\n", integer, thing); } } ```
Re: Custom type / Typle type formatted reader
🤔I'm either asking a stupid question, asking it in a wrong way, or asking an important question. Clueless nontheless. . .
Re: Reading files using delimiters/terminators
On Tuesday, 29 December 2020 at 14:50:41 UTC, Steven Schveighoffer wrote: Are you on Windows? If so, your double newlines might be \r\n\r\n, depending on what editor you used to create the input. Use a hexdump program to see what the newlines are in your input file. I've tried \r\n\r\n as well, which sadly also did not work. Using vscode I have also switched between CRLF and LF, which also did not do the trick. I'm getting the sense the implementation might have a specific workaround for \r\n / CRLF line-endings, though I haven't checked the sourcecode yet. Note that this is not really a problem for me specifically, I've long used a different approach, however it seemed like a design issue. I'll try replicating this in isolation later, maybe something was wrong last time I tried.
Re: C++ or D?
On Tuesday, 29 December 2020 at 16:13:50 UTC, Imperatorn wrote: https://ibb.co/syQRs9v I hope I'm not the only one that thinks 'designers and std lib writers unable to name anything correctly' is kind of ironic. And don't get me started on documentation return values.
Re: Reading files using delimiters/terminators
http://ddili.org/ders/d.en/index.html This seems very promising :) I doubt I'd still be considering D if it weren't for this awesome learning forum, thanks for all the help!
Custom type / Typle type formatted reader
It's more of a multi-part question, I've been trying to read tuples using 'slurp', though later realised one of the types was an enum, I'm guessing that's what was the problem, which lead me down a whole rabbit hole. - Can I directly read tuples using slurp? It doesnt seem to like slurp!TUPLE_ALIAS_HERE(etc - Since slurp can read files into tuples, can I somehow tell slurp to name the fields? (For example, I have `alias Instruction = Tuple!(OPERATION, "operation", int, "argument");`, but I'm not sure if it's possible to make slurp output one), or alternatively, can I define it's output tuple 'type'? - If it's possible to make user types print in certain ways (https://wiki.dlang.org/Defining_custom_print_format_specifiers), is it possible to also read them back? Say using formattedRead or slurp or parse or even to? And if so, how does this work? - Is it possible to read (formatted) data into enums, as for example I would like? I wouldnt be surprised if this question stands loose from the previous one, as it's not entirely the same situation. I have an enum; enum OPERATION {NOP, // Would like to read 'nop' hereto ACCUMULATE, // 'acc' likewise JUMP // and 'jmp' }
Re: Reading files using delimiters/terminators
On Sunday, 27 December 2020 at 23:12:46 UTC, Rekel wrote: Sidetangent, don't mean to bash the learning tour, as it's been really useful for getting started, but I'm surprised stuff like tuples and files arent mentioned there. Update; Any clue why there's both "std.file" and "std.io.File"? I was mostly unaware of the former.
Re: Reading files using delimiters/terminators
On Sunday, 27 December 2020 at 13:27:49 UTC, oddp wrote: foreach (group; readText("input").splitter("\n\n")) { ... } Also, on other days, when the input is more uniform, there's always https://dlang.org/library/std/file/slurp.html which makes reading it in even easier, e.g. day02: alias Record = Tuple!(int, "low", int, "high", char, "needle", string, "hay"); auto input = slurp!Record("input", "%d-%d %s: %s"); P.S.: would've loved to have had multiwayIntersection in the stdlib for day06 part2, especially when there's already multiwayUnion in setops. fold!setIntersection felt a bit clunky. Oh my, all these things are new to me, haha, thanks a lot! I'll be looking into those (slurp & tuple). By the way, is there a reason to use either 'splitter' or 'split'? I'm not sure I see why the difference would matter in the end. Sidetangent, don't mean to bash the learning tour, as it's been really useful for getting started, but I'm surprised stuff like tuples and files arent mentioned there. Especially since the documentation tends to trip me up, with stuff like 'isSomeString' mentioning 'built in string types', while I haven't been able to find that concept elsewhere, let alone functionality one can expect in this case (like .length and the like), and stuff like 'countUntil' not being called 'indexOf', although it also exists and does basically the same thing. Also assumeUnique seems to be a thing?
Re: Reading files using delimiters/terminators
On Sunday, 27 December 2020 at 02:41:12 UTC, Jesse Phillips wrote: Unfortunately std.csv is character based and not string. https://dlang.org/phobos/std_csv.html#.csvReader But your use case sounds like splitter is more aligned with your needs. https://dlang.org/phobos/std_algorithm_iteration.html#.splitter But I'm not using csv right? Additionally, shouldnt byLine also work with "\r\n"?
Reading files using delimiters/terminators
I'm trying to read a file with entries seperated by '\n\n' (empty line), with entries containing '\n'. I thought the File.readLine(KeepTerminator, Terminator) might work, as it seems to accept strings as terminators, since there seems to have been a thread regarding '\r\n' seperators. I don't know if there's some underlying reason, but when I try to use "\n\n" as a terminator, I end up getting the entire file into 1 char[], so it's not delimited. Should this work or is there a reason one cannot use byLine like this? For context, I'm trying this with the puzzle input of day 6 of this year's advent of code. (https://adventofcode.com/)
Re: Slice allocation after appending
On Wednesday, 23 December 2020 at 04:03:37 UTC, Ali Çehreli wrote: It is valid. One can always copy the small array before appending to it and the large array would be preserved. Try the -profile command line switch when compiling your program and it will show where memory allocations occur. Very helpful in exposing such problem spots... Ali I'm not sure what your aliasSeq does, sadly I don't find the documentation's explanation satisfactory. Though thank's a lot, now I know what to take into account, & I didn't know about the -profile switch yet ^^
Slice allocation after appending
According to the D slice article (https://dlang.org/articles/d-array-article.html), slices do not care where they start, only where they end, when checking whether expanding in place is permitable, or at least that is what I understood regarding it. Now I'm unsure how to check this, I tried to a bit using the online editor and a bit of pointer usage which seemed to confirm my suspicion, but does this mean that taking a (small) slice at the end of a (possibly) very large dynamic array can lead to problematic behavior? For example; int[] a = new int[10]; // Imagine this is very large int[] b = a[$-1..$]; // Small slice at the end b ~= 2;// b extends, possibly in place a ~= -1; // a no longer can, so the entire array needs reallocating (instead of be reallocating & a growing in place) Again I'm not very certain I fully understood how slices are implemented, but is this example, and the problem I imagine it leading to, valid?
Re: Trying to understand multidimensional arrays in D
On Tuesday, 22 December 2020 at 16:55:40 UTC, Mike Parker wrote: On Tuesday, 22 December 2020 at 15:31:06 UTC, Rekel wrote: Don't take that as a defence of changing pointer syntax by the way, just noting I think the argument pointers and arrays should be defined using a similar syntax is not consistent when thinking about indexing & dereferencing. Besides, I think '[4]foo* foos;' is quite clear. "array of foo pointers" seems very natural to me. Ugh. No thanks :-) My brain would short circuit every time I see it. I take it you're not open to considering [4]*foo either? I feel like there are quite strong argument for it, regarding readability & (definition vs operator) consistency.😅
Re: Trying to understand multidimensional arrays in D
On Tuesday, 22 December 2020 at 16:56:18 UTC, Ali Çehreli wrote: >[4]Foo b; /* an array of four Foos */ [4] already has a meaning. ;) It does in that context? Do tell, I'm unaware. Also, is it possible to move entire thread to a different forum group? 😂 This feels more like a discussion fit for 'general'.
Re: Trying to understand multidimensional arrays in D
On Tuesday, 22 December 2020 at 15:24:04 UTC, Rekel wrote: The way C syntax handles pointers isn't very consistent to begin with imo. It's strange & and * are prepended to pointer variables for example, while indexing is postpended. Leads to stuff like; (*array_of_pointers_to_arrays[2])[1] vs array_of_pointers_to_arrays[2]*[1] and (*array_of_pointers[1]).x' vs 'array_of_pointers[1]*.x' Don't take that as a defence of changing pointer syntax by the way, just noting I think the argument pointers and arrays should be defined using a similar syntax is not consistent when thinking about indexing & dereferencing. Besides, I think '[4]foo* foos;' is quite clear. "array of foo pointers" seems very natural to me.
Re: Trying to understand multidimensional arrays in D
On Tuesday, 22 December 2020 at 14:15:12 UTC, Mike Parker wrote: [][4]Foo is completely backwards from and inconsistent with the pointer declaration syntax. We shouldn't want to intentionally introduce inconsistencies. The way C syntax handles pointers isn't very consistent to begin with imo. It's strange & and * are prepended to pointer variables for example, while indexing is postpended. Leads to stuff like; (*array_of_pointers_to_arrays[2])[1] vs array_of_pointers_to_arrays[2]*[1] and (*array_of_pointers[1]).x' vs 'array_of_pointers[1]*.x' On Tuesday, 22 December 2020 at 14:35:30 UTC, ag0aep6g wrote: But now we're no longer C-like, I guess. I think it'd still be quite C-like, same concepts samilar usage. You're not using 'int foo[]' syntax anymore anyhow.
Re: Trying to understand multidimensional arrays in D
On Tuesday, 22 December 2020 at 07:19:49 UTC, Ali Çehreli wrote: Let me try the history example: Row[4][] history; Row array (of 4) array. Fully disagreed: D's array syntax makes me happy; designed right. :) I think i see your point, strange how a change of words makes some things make more sense. I'll do my best to think of it like that, even if i find it intuïtive. 😅 I am curious by the way, what do you think of the [][4]Row suggestion I gave? In a way you'd have your 🍰 & could eat it too, i think ^^ (Still a strange saying to me)
Re: Trying to understand multidimensional arrays in D
Small addition, not out of jest; If plug and play consistency given aliases is required (which seems pointless, as they exit to be used), the best solution, which would avoid indexing inconsistency given regular reading order, would be the following; alias Row = [3]int; [1][2][3]int history; int last_element = history[0][1][2]; [1][2]Row history; int last_element = history[0][1][2]; Row last_row = history[0][1]; This would be consistent, and readable.
Re: Trying to understand multidimensional arrays in D
On Monday, 30 January 2017 at 07:33:34 UTC, Ali Çehreli wrote: As others have said, D's array definition is natural because unlike C's inside-out (or is that outside-in?) syntax, it follows from the alias syntax. Replacing History inside main with Matrix[], etc.: History history;// is the same as: Matrix[] history; // is the same as: Row[4][] history; // is the same as: int[4][4][] history; Ali Defending array-notation by giving an example of explicitly not using declared aliases makes no sense to me. When I define 2d arrays, or index them, I think in row -> column terms (often math notation for matrix size being; 'rows x columns'), or more generally in big -> small terms, which is clear when using the consistent left->right notation, big picture first followed by detail, honestly the whole concept of encapsulation; History history; Matrix[] history; Row[][4] history; // collection of rows, stored in a dynamic array (top level), each containing 4 (in detail). int[][4][4] history; // collection of integers, stored in a dynamic array (top level), containing 4 rows (->middle level->) of 4 columns (in detail), Of course, one can also prefer storing in columns, instead of rows, even glsl uses column-major order, just change 'Row' to 'Column' and you're set. My argument here of course rests on outside->in thinking, which one can reverse consistently. I would be fine with that. At heart however, this declaration design leads to inconsistency. int[1][2] history; // 1 columm, 2 rows vs int last_element = history[1][0] // row 1, column 0 This makes no sense to anyone used to reading left to right, or even right to left. Honestly, reversing reading-order when indexing & declaring is the worst idea I could imagine if consistency and readability were your goal. It doesn't make more sense because you're reading 'outward', that would mean I would have to read both left to right _and_ right to left. The argument Jonathan M Davis gives in this regard hold no water for me. Like in C/C++, types are mostly read outward from the variable name in D. In both C/C++ and D, int* foo; is a pointer to an int. It's read outward from the variable name, so you get the pointer and then what it points to. Similarly, int** foo; is a pointer to a pointer to an int. Feel free to read them the way you want, but personally, I read int* foo as 'integer pointer', which is not 'outward'. Your argument is only based on personal reading preference, but with it you remove indexing consistency & introduce boustrophedon. You don't even always have the variable name; ... = new int[1][2] vs ... = new int[][](2, 1) If you were to ask someone with no prior coding experience how to access a predefined declaration, given a onedimensional explanation, I'm certain they would default to standard western reading order, no matter the presence of a variable name. I'm surprised this thread is 3 years old by the way, sorry for that, just noticed this is how D handles multidimensional arrays (I may add a note about this to the tour suggestions). It saddens me quite a bit, as I see it as a big design flaw and quite a turn-off, "unfortunately one that can't be fixed" as Profile Analysis put it. Have a nice & safe christmas! - Rekel, the disproportionally active forum . . . person (sorry)
Re: Flag & byLine confusion.
On Sunday, 20 December 2020 at 15:04:29 UTC, Steven Schveighoffer wrote: On 12/20/20 9:07 AM, Rekel wrote: Does this mean other flag yes's will not be accepted? The long and short of it is that Flag is supposed to make you NAME what your flag is for. The idea is to prevent things like: byLine(true); Reading the code, what does "true" mean? You have to look up the documentation to see what it is. And then you might have things like: foo(true, true, false, true); What do all those mean? Instead, you have to name what the flag is for: byLine(KeepTerminator.yes); The Yes/No structs and Flag structs are there to help you name your flag, and have some awkward D way to do this. This will likely all go away in the future with named parameters (deprecating Flag is one of the reasons named parameters were proposed/accepted). I personally avoid Flag in my code because I think it's awkward and cumbersome. -Steve With named parameters, do you refer to python-esque function calls? That makes a lot more sense to me personally, although I'm only just learning D, as I likewise wouldnt use `Number!"Wheels".4` for a function call. By the way, where can I see Flag is (/ will be?) deprecated? It doesn't show in the library reference, however I may be looking in the wrong place.
Re: If statements and unused template parameters in Phobos documentation
On Sunday, 20 December 2020 at 13:58:00 UTC, Max Haughton wrote: The if is a template constraint. Ah sorry! I must have missed that part of the dlang tour. (https://tour.dlang.org/tour/en/gems/template-meta-programming) Thanks a lot!
Re: Flag & byLine confusion.
Thanks for all the help! This makes it make a lot more sense now, I'm surprised it's not part of the dlang tour. The template parameter serves to make Flag!"foo" a distinct type from Flag!"bar". Does this mean other flag yes's will not be accepted? https://dlang.org/spec/operatoroverloading.html#dispatch Also regarding the other examples given, why does Phobos use templating so heavily, in situation in which I am totally confused as to why generics would be necessary. I seem to be totally confused as to how this template system works. It was introduced as a kind of generic, like in Java, but things like 'string s' seem to me like parameters. For example; ``` class C { void opDispatch(string s)(int i) { writefln("C.opDispatch('%s', %s)", s, i); } } ``` I'm pretty sure I'm confusing something, though I don't see the point of using this instead of something like 'opDispatch(string s, int i)`? I also came across a similar thing in the File.byLine documentation. (https://dlang.org/library-prerelease/std/stdio/file.by_line.html)
If statements and unused template parameters in Phobos documentation
I found a lot of the Phobos documentation to contain template arguments and if statements that made no sense to me, for example: ``` uint readf(alias format, A...) ( auto ref A args ) if (isSomeString!(typeof(format))); uint readf(A...) ( scope const(char)[] format, auto ref A args ); ``` https://dlang.org/library/std/stdio/file.readf.html From stdio.readf & stdio.File.readf. I'm assuming this is some kind of template, but often it seems there are more parameters in the first '()' part than are ever given. Am I missing something? Additionally, what is that if statement for? It precedes nothing.
Flag & byLine confusion.
After reading most of the tour.dlang.org website, I was completely surprised & confused encountering 'KeepTerminator', a 'Flag' used by the File.byLine function. With no examples denoting how to use it. Most confusing was the way the documentation (website & in-editor) used; 1. Yes.keepTerminator 2. KeepTerminator.yes 3. Flag!"keepTerminator".yes & Don't get me started on the autocomplete trying to get me to use KeepTerminator.Flag.yes (VSCode & code-d) Now some documentation stated these flags are used to improve readability, when compared to simple booleans, but all these different notations seem super confusing, especially since I dont understand why Flag requires a !"Name" part. And I haven't read anything about it in the language tour, nor have I found any discussion on the topic elsewhere. I did find, for some reason, a second 'KeepTerminator' documentation page . . . which is from std.string, which understandably did not help clear things up. Even further confused by the in-editor documentation, is this function a template?: " byLine(Terminator = char, Char = char) (KeepTerminator keepTerminator = No,keepTerminator, Terminator terminator = '\\n') " I'm sorry, I may be asking for too much, but I've got so many questions and found few answers. 1. Did I miss some tutorial? 2. Why does flag require a name (!"Name")? 3. Is byLine a template, if so, how would one use it differently?