Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On Monday, 8 June 2020 at 19:05:45 UTC, Steven Schveighoffer wrote: On 6/8/20 2:53 PM, mw wrote: And with a symbol-to-c-func table, it should be able to just call that C func. Consider that the libc available to the compiler might not be the same as the libc for the target (e.g. cross compilation). Not just that, but this opens the compiler up to a huge hole of unpredictability and security. I head that. But, can we take a pragmatic approach, not the "all-or-none" approach as I talked about in the other MI thread: (https://forum.dlang.org/post/lsnhqdoyatkzbzqbs...@forum.dlang.org) We can have an approved list of C funcs that allowed to be called during CTFE? e.g. math funcs about numbers, but not network or string C funcs. Most people define static const for some numerical values, allow C math func at CTFE may solve a large part of the problems (80-90%? just my guess).
Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On 6/8/20 2:53 PM, mw wrote: And with a symbol-to-c-func table, it should be able to just call that C func. Consider that the libc available to the compiler might not be the same as the libc for the target (e.g. cross compilation). Not just that, but this opens the compiler up to a huge hole of unpredictability and security. -Steve
Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On Monday, 8 June 2020 at 18:43:58 UTC, Stanislav Blinov wrote: On Monday, 8 June 2020 at 18:08:57 UTC, mw wrote: 2) even it does so, but why such simple function as lroundl cannot be CTFE-ed? Because, as the error message states, there's no source for it :) std.math calls into C math library. OK, but the compiler knows it's external C func: return core.stdc.math.llroundl(x); And with a symbol-to-c-func table, it should be able to just call that C func. This is dramatically enhance CTFE's eval ability, esp for math funcs.
Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On 6/8/20 2:08 PM, mw wrote: Hi, I'm trying to build this package: https://code.dlang.org/packages/fixed however, the compiler error out: ldc2-1.21.0-linux-x86_64/bin/../import/std/math.d(5783,39): Error: llroundl cannot be interpreted at compile time, because it has no available source code Looks like it does some CTFE, but 1) I cannot find where CTFE happens in: https://github.com/jaypha/fixed/blob/master/src/jaypha/fixed.d Are you statically initializing a Fixed type? e.g. (in global scope): auto myFixedVal = Fixed!2("1.5"); That constructor call is done via CTFE. The constructor calls std.math.lround. lround uses libc, which has no source available. 2) even it does so, but why such simple function as lroundl cannot be CTFE-ed? The simplicity of the function has nothing to do with whether it can be CTFE. It has to do with the source code being available (as the error message indicates). Note that the fix for the package would be to have an alternate CTFE branch, or to quit using libc. An alternative package was created here to fix a different issue (that strings are converted to double to convert to the proper integer type), but it too will use libc when initializing a fixed point type from a double: https://github.com/m3m0ry/fixedpoint So depending on your usage, it may solve your problem. Plus, it's actually being currently maintained, I don't think the original package is. -Steve
Re: Dub Error Message "Invalid variable: DUB"
On Monday, 8 June 2020 at 18:38:17 UTC, Paul Backus wrote: On Monday, 8 June 2020 at 17:55:24 UTC, Andre Pany wrote: I had a second look on the descriptions and from a non native speaker view it sounds correct. But you are right from a native speaker view the wording might be incorrect. If you have time, could you check the wording and make a proposal? https://github.com/dlang/dub-docs/blob/master/views/inc.package_format.envvars.dt Kind regards Andre https://github.com/dlang/dub-docs/pull/26 Thanks a lot. Kind regards Andre
Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On Monday, 8 June 2020 at 18:08:57 UTC, mw wrote: 2) even it does so, but why such simple function as lroundl cannot be CTFE-ed? Because, as the error message states, there's no source for it :) std.math calls into C math library.
Re: Dub Error Message "Invalid variable: DUB"
On Monday, 8 June 2020 at 17:55:24 UTC, Andre Pany wrote: I had a second look on the descriptions and from a non native speaker view it sounds correct. But you are right from a native speaker view the wording might be incorrect. If you have time, could you check the wording and make a proposal? https://github.com/dlang/dub-docs/blob/master/views/inc.package_format.envvars.dt Kind regards Andre https://github.com/dlang/dub-docs/pull/26
Error: llroundl cannot be interpreted at compile time, because it has no available source code
Hi, I'm trying to build this package: https://code.dlang.org/packages/fixed however, the compiler error out: ldc2-1.21.0-linux-x86_64/bin/../import/std/math.d(5783,39): Error: llroundl cannot be interpreted at compile time, because it has no available source code Looks like it does some CTFE, but 1) I cannot find where CTFE happens in: https://github.com/jaypha/fixed/blob/master/src/jaypha/fixed.d 2) even it does so, but why such simple function as lroundl cannot be CTFE-ed?
Re: Dub Error Message "Invalid variable: DUB"
On Sunday, 7 June 2020 at 16:54:48 UTC, Paul Backus wrote: On Sunday, 7 June 2020 at 16:26:17 UTC, Andre Pany wrote: On Sunday, 7 June 2020 at 15:37:27 UTC, Paul Backus wrote: On Sunday, 7 June 2020 at 12:52:12 UTC, Andre Pany wrote: I am not sure but $DUB is a variable which could be used in dub descriptor file but it isn't an environment variable. $DUB_EXE is an environment variable. Kind regards Andre If what you say is true, the Dub documentation needs to be updated: https://dub.pm/package-format-json.html#environment-variables Each of the table has an explanation section were they can be used. $DUB can only be used within the dub descriptor but not within scripts called from the hooks. From the hooks you can use these environment variables: https://github.com/andre2007/dub/blob/376ff5854dcd7bbc6116f72001c8c6d13eb3cbf0/source/dub/generators/generator.d#L763 Kind regards Andre The documentations says: Inside of custom commands directives a number of additional variables is available: ...and then lists the variables from the function you linked to. "Additional" implies that they are not the only variables that can be used in hooks, and that the variables listed previously (such as $DUB) can also be used. If this is not the case, then the documentation is inaccurate and should be updated. I would also add: if you feel the need to link to the source code to explain to use a feature, rather than referring to the documentation, that is a good sign that the documentation is inadequate. I had a second look on the descriptions and from a non native speaker view it sounds correct. But you are right from a native speaker view the wording might be incorrect. If you have time, could you check the wording and make a proposal? https://github.com/dlang/dub-docs/blob/master/views/inc.package_format.envvars.dt Kind regards Andre
Re: Mixin and imports
On Monday, 8 June 2020 at 16:02:02 UTC, Steven Schveighoffer wrote: On 6/8/20 11:11 AM, jmh530 wrote: On Monday, 8 June 2020 at 14:27:26 UTC, data pulverizer wrote: [snip] Out of curiosity what does the "." in front of `foo` mean? [snip] ag0aep6g provided the link to it [snip] The dot operator simply specifies that the symbol you are looking for is defined at global scope, so it just changes the lookup rules. Even though it makes the code clearer what foo you are looking at, it was not necessary -- removing the dot works. In some cases it is necessary to use the . lookup rule, because you have another symbol that will be picked first. For example: int x; template bar(string x) { mixin("alias " ~ x ~ " = .x;"); } -Steve Thanks both of you. It's one of those puzzling things that was at the back of mind that has just been resolved.
Re: Mixin and imports
On 6/8/20 11:11 AM, jmh530 wrote: On Monday, 8 June 2020 at 14:27:26 UTC, data pulverizer wrote: [snip] Out of curiosity what does the "." in front of `foo` mean? I've seen that in some D code on the compiler in GitHub and have no idea what it does. I tried Googling it to no avail. It doesn't have anything to do with UFCS does it? Thanks ag0aep6g provided the link to it, but it's one of those things that has been difficult for me to understand as well. I believe the original code had `foo` in a template. So in that case it was necessary. I'm not sure if it still is in my simplified version. The dot operator simply specifies that the symbol you are looking for is defined at global scope, so it just changes the lookup rules. Even though it makes the code clearer what foo you are looking at, it was not necessary -- removing the dot works. In some cases it is necessary to use the . lookup rule, because you have another symbol that will be picked first. For example: int x; template bar(string x) { mixin("alias " ~ x ~ " = .x;"); } -Steve
Re: Mixin and imports
On Monday, 8 June 2020 at 14:27:26 UTC, data pulverizer wrote: [snip] Out of curiosity what does the "." in front of `foo` mean? I've seen that in some D code on the compiler in GitHub and have no idea what it does. I tried Googling it to no avail. It doesn't have anything to do with UFCS does it? Thanks ag0aep6g provided the link to it, but it's one of those things that has been difficult for me to understand as well. I believe the original code had `foo` in a template. So in that case it was necessary. I'm not sure if it still is in my simplified version.
Re: Metaprogramming with D
On Monday, 8 June 2020 at 14:41:55 UTC, Jan Hönig wrote: What is the name of this `q` thing? It is just a string that looks like code.
Re: Metaprogramming with D
On 08.06.20 16:45, ag0aep6g wrote: On 08.06.20 16:41, Jan Hönig wrote: On Sunday, 7 June 2020 at 00:45:37 UTC, Ali Çehreli wrote: [...] writeln(q{ void foo() { } }); What is the name of this `q` thing? How do i find it? Are there any recent tutorials on it? https://dlang.org/spec/lex.html#token_strings https://ddili.org/ders/d.en/literals.html#ix_literals.q{} Hm. That second link is somewhat malformed. Better one: https://ddili.org/ders/d.en/literals.html#ix_literals.q%7B%7D
Re: Metaprogramming with D
On 08.06.20 16:41, Jan Hönig wrote: On Sunday, 7 June 2020 at 00:45:37 UTC, Ali Çehreli wrote: [...] writeln(q{ void foo() { } }); What is the name of this `q` thing? How do i find it? Are there any recent tutorials on it? https://dlang.org/spec/lex.html#token_strings https://ddili.org/ders/d.en/literals.html#ix_literals.q{}
Re: Metaprogramming with D
On Sunday, 7 June 2020 at 00:45:37 UTC, Ali Çehreli wrote: dmd -mixin= ... thanks for the tip! writeln(q{ void foo() { } }); What is the name of this `q` thing? How do i find it? Are there any recent tutorials on it?
Re: Mixin and imports
On 08.06.20 16:27, data pulverizer wrote: Out of curiosity what does the "." in front of `foo` mean? I've seen that in some D code on the compiler in GitHub and have no idea what it does. I tried Googling it to no avail. It doesn't have anything to do with UFCS does it? https://dlang.org/spec/module.html#module_scope_operators
Re: Mixin and imports
On Monday, 8 June 2020 at 02:55:25 UTC, jmh530 wrote: ``` ... template foo(string f) { mixin("alias foo = .foo!(" ~ f ~ ");"); } ... ``` Out of curiosity what does the "." in front of `foo` mean? I've seen that in some D code on the compiler in GitHub and have no idea what it does. I tried Googling it to no avail. It doesn't have anything to do with UFCS does it? Thanks
Re: Metaprogramming with D
On Sunday, 7 June 2020 at 00:45:37 UTC, Ali Çehreli wrote: On 6/6/20 5:03 PM, FunkyD wrote:> On Saturday, 6 June 2020 at 09:57:36 UTC, Jan Hönig wrote: > D is pretty good for meta-programming. For certain other things it is > terrible. I am glad I don't know enough about other technologies to feel that way. Ok, that isn't my fault. > String mixins simply mix in D code. It lets you build generic D code. > The big problem here is debugging. There is ZERO ability to properly > debug string mixins. "Zero" is too strong an assertion and because of the following, false: You know the difference between logic and statistics? Ever heard of measure theory? It's a pretty poor argument to claim that "Oh, logically it is not 100% true so it can't be true at all". I'm fine with stating something as All if it's true 98%+ of the time when it doesn't matter if it's 90% or 100% or anything in between. If, for example, you had cancer almost all over your body I don't think someone you fault you if you said all instead of almost all. Pedanticism usually isn't a feature but a fault. dmd -mixin= ... > Well, what it boils down to is writing out the > string mixin and then debugging that. When I compile my program and there is an issue with a string mixin, Emacs opens the mixin file and shows me the compilation there. This is because dmd's error include the exact line in the where my mixin was broken. Not a shiny IDE but still pretty awesome support. > It would be nice if D had a special D code string that the IDE could > interpret properly. I must be misunderstanding you but it must be an IDE limitation because of the following: writeln(q{ void foo() { } }); My IDE gives me syntax highlighting in that string, so it works somehow. Syntax highlighting is entirely different from semantic analysis. Try getting a line number of an error a multi-line string... > D basically tries to resolve things after the fact so > > R add(T)(T a, T b) > { > return a + b; > } > > this will attempt to + on a and b after the types are known. If they > can't be added then an error will occur, which is usually cryptic for > templates. That's why we use template constraints and in some cases 'static assert' for custom error messages. Yeah, that is definitely not the way to go... I could just throw rocks at my computer until it works too. Just because one can do it doesn't mean one should. In this case one is nearly forced. Claiming that because we have the most primitive form of a solution makes up for having a good solution is pretty primitive. > The issue in using D should not be made based on it's metaprogramming. I agree. What feature to use usually emerges by itself. For example, when an algorithm is repeated for many types, it is an opportunity for templates. > D, IMO, is not capable of writing sophisticated programs... "Sophisticated" is relative but such strong assertions can be falsified by a single counterexample. For example, Weka's product is very sophisticated and is written in D. And there is nothing extra or missing in D that makes it incapable in that regard. As you said, sophisticated is quite relative. It seems you seem to think this is a math pissing contest. Anyone that makes a decision based on logical facts rather than statistical facts for statistical problems is quite illogical. > this is why > you do not see any. I think the fact that many smart programmers are hostage to other languages is a stronger reason. Maybe, maybe not... sounds like an excuse. Maybe they are actually rational beings who understanding that moving to an unpredictable and rather incompletely language is not worth the trouble? > No one writes large commercial apps in D. False. Prove it. Saying something is false is not the same as it being false. Since you want to play hardball: Name one commercial D app that has over 1 million in revenue and is used by 10k people. Just one. I'll let you play your games. Here I'm talking about an actual app that is entirely written in D. You cannot claim an app is written in D when it just imports some D library. Nor are we talking about ad revenue generating software. I'm talking about something normal people use as an application... like a word processor, painting app, web browser, etc. Something external users use, not a internal to a company. Just one, come on, you said it was easy! > There is > not one! False. And again, even if so, that's not because of D, but because of humans. Can you imagine a CTO, say, in Silicon Valley to have guts to bring D instead of C++? With C++, the CTO will never be blamed; but D, he or she can easily be blamed upon failure. Not because of the technologies but because of politics. Now you are claiming that they don't exist. Which is it? Do they exist or do they not exist and they don't exist for some ad hoc theories you have? > The
Re: Mixin and imports
On Monday, 8 June 2020 at 12:20:46 UTC, Adam D. Ruppe wrote: [snip] Why do you even want foo!"fabs"? Usually when I see people having this problem it is actually a misunderstanding of what is possible with the foo!fabs style - which is better in basically every way and can be used in most the same places. So what's your bigger goal? There were some other functions in the module that allow the use of function!"thinginquotes". However, most of those functions are using the "thinginquotes" to avoid writing function!(SomeEnum.thinginquotes). That really isn't the thing to fix in this case. So I think it makes sense for me to give up what I was trying to do.
Re: Mixin and imports
On Monday, 8 June 2020 at 10:41:53 UTC, jmh530 wrote: On Monday, 8 June 2020 at 10:28:39 UTC, Paul Backus wrote: [snip] Thanks for that suggestion. That works for me. Unfortunately, it's probably not worth the extra effort though, versus doing foo!fabs in my case. If they are all from std.math you can easily mixin in the template. just import std.math there then it should work. If you want more general arbitrary functions you can get the module of the function by using an alias. Alternatively you can just pass the function itself as an alias or template parameter. There are ways to do what you want but it's kinda hacky. I can't remember the details though. Basically you use mixins and traits to get the module the symbol exists in and then you can use a string mixin to import that module.
Re: Mixin and imports
On Monday, 8 June 2020 at 02:55:25 UTC, jmh530 wrote: In the code below, foo!fabs compiles without issue, but foo!"fabs" does not because the import is not available in the string mixin. Why do you even want foo!"fabs"? Usually when I see people having this problem it is actually a misunderstanding of what is possible with the foo!fabs style - which is better in basically every way and can be used in most the same places. So what's your bigger goal?
Re: how to append (ref) int[] to int[][]?
On Monday, 8 June 2020 at 06:52:36 UTC, mw wrote: On Monday, 8 June 2020 at 06:42:44 UTC, Simen Kjærås wrote: Arrays (technically, slices) in D are essentially this struct: struct Array(T) { T* ptr; size_t length; // operator overloads } So when you have int[][], each element of the outer array is an Array!int. These, as simple structs, are copied about, so that changing one does not change another. Thank you for the reply, I think this explanation should be added to the top of https://dlang.org/spec/arrays.html Then people (esp with C/C++ background) can easily understand D's array behavior. A good explanation of D's arrays (which should really be called "slices") is available in the "Articles" section of dlang.org: https://dlang.org/articles/d-array-article.html
Re: how to append (ref) int[] to int[][]?
On Monday, 8 June 2020 at 06:13:36 UTC, mw wrote: what I really want in (a) is append `ref arr` and output [[3], [3], [3]], i.e. the real `arr` be appended instead of its copy. I tried to change arrs' decl to: (ref (int[]))[] arrs; // the intended semantics I want 1) I'm wondering how to achieve what I want? and 2) why "~=" here will append a copy rather than the real `arr` itself to arrs? Thanks. ``` import std.stdio; void f(ref int[] arr) { arr ~= 3; } void main() { import std.algorithm; int[]*[] arrs; int[]* arr; foreach (i; 0 .. 3) { //stack allocated array pointer would expire on end of scope, so must allocate the them on heap since we're keeping refeerences on them. auto arrayAllocation = new int[][1]; arr = [0]; *arr = new int[0]; arrs ~= arr; f(*arr); } //will print an array of addresses otherwise arrs.map!(ptr => *ptr).writeln; } ``` But I must say I would generally prefer just calling `f()` on `arrs[i]` directly after appending, or calling the function before appending. One reason is that needless heap usage is generally less efficient than using the stack.
Re: Mixin and imports
On Monday, 8 June 2020 at 10:28:39 UTC, Paul Backus wrote: [snip] Thanks for that suggestion. That works for me. Unfortunately, it's probably not worth the extra effort though, versus doing foo!fabs in my case.
Re: `this` template params for struct not expressing constness.
On Monday, 8 June 2020 at 09:08:40 UTC, adnan338 wrote: On Monday, 8 June 2020 at 08:10:19 UTC, Simen Kjærås wrote: On Monday, 8 June 2020 at 07:35:12 UTC, adnan338 wrote: Self* searchTree(this Self)(auto in ref T item) const { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } This method is const, which means 'this' is const, while Self is not. What you're looking for here is inout (https://dlang.org/spec/function.html#inout-functions): auto searchTree()(auto in ref T item) inout { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } -- Simen Thank you. Few followup questions, if you don't mind. 1. What does that blank template parameter mean? Just forces the function to be a template. The only reason for this is it's required for auto ref to work, which you may or may not need on that function. 2. Since `inout` acts as a wildcard for immutable/const/non-const qualifiers, what should I do to have the compiler ensure that my method does not mutate a non-const tree inside the body? Inside inout functions, `this` is treated as const - any attempt to modify it should give a compile error. Since D const is transitive, anything reachable from `this` is also treated as const. If you're able to mutate a non-const tree inside the body, there's a bug in the compiler. -- Simen
Re: Mixin and imports
On Monday, 8 June 2020 at 10:23:24 UTC, jmh530 wrote: On Monday, 8 June 2020 at 04:13:08 UTC, Mike Parker wrote: [snip] The problem isn't the mixin. It's the template. Templates take the scope of their declaration, not their instantiation. So the mixin is getting the template's scope. Anyway, this appears to work: `double z = foo!"std.math.fabs"(x);` Thanks, that makes sense. However, I get the same error with the code below. Am I doing something wrong? double foo(alias f)(double x) { return f(x); } template foo(string f) { mixin("alias foo = .foo!(" ~ f ~ ");"); } void main() { static import std.math; double x = 2.0; double y = foo!(std.math.fabs)(x); double z = foo!"std.math.fabs"(x); } If you want to refer to symbols in the scope where the template is instantiated, you will have to move the mixin outside of the template: double foo(alias f)(double x) { return f(x); } template foo(string f) { enum foo = "foo!(" ~ f ~ ")"; } void main() { import std.math: fabs; double x = 2.0; double y = foo!(fabs)(x); double z = mixin(foo!"fabs")(x); }
Re: Mixin and imports
On Monday, 8 June 2020 at 04:13:08 UTC, Mike Parker wrote: [snip] The problem isn't the mixin. It's the template. Templates take the scope of their declaration, not their instantiation. So the mixin is getting the template's scope. Anyway, this appears to work: `double z = foo!"std.math.fabs"(x);` Thanks, that makes sense. However, I get the same error with the code below. Am I doing something wrong? double foo(alias f)(double x) { return f(x); } template foo(string f) { mixin("alias foo = .foo!(" ~ f ~ ");"); } void main() { static import std.math; double x = 2.0; double y = foo!(std.math.fabs)(x); double z = foo!"std.math.fabs"(x); }
Re: `this` template params for struct not expressing constness.
On Monday, 8 June 2020 at 08:10:19 UTC, Simen Kjærås wrote: On Monday, 8 June 2020 at 07:35:12 UTC, adnan338 wrote: Self* searchTree(this Self)(auto in ref T item) const { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } This method is const, which means 'this' is const, while Self is not. What you're looking for here is inout (https://dlang.org/spec/function.html#inout-functions): auto searchTree()(auto in ref T item) inout { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } -- Simen Thank you. Few followup questions, if you don't mind. 1. What does that blank template parameter mean? 2. Since `inout` acts as a wildcard for immutable/const/non-const qualifiers, what should I do to have the compiler ensure that my method does not mutate a non-const tree inside the body?
Re: `this` template params for struct not expressing constness.
On Monday, 8 June 2020 at 07:35:12 UTC, adnan338 wrote: Self* searchTree(this Self)(auto in ref T item) const { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } This method is const, which means 'this' is const, while Self is not. What you're looking for here is inout (https://dlang.org/spec/function.html#inout-functions): auto searchTree()(auto in ref T item) inout { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } -- Simen
Re: `this` template params for struct not expressing constness.
On Monday, 8 June 2020 at 07:35:12 UTC, adnan338 wrote: Hi, as far as I understand, the `this` template parameter includes constness qualifiers as seen in https://ddili.org/ders/d.en/templates_more.html To apply this I have this following struct: module bst; struct Tree(T) { T item; Tree!T* parent, left, right; this(T item) { this.item = item; } Self* searchTree(this Self)(auto in ref T item) const { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } } unittest { auto text1 = "Hello", text2 = "World"; auto tree2 = Tree!string(text1); assert(tree2.searchTree(text2) is null); assert(tree2.searchTree(text1) !is null); auto tree1 = Tree!int(4); assert(tree1.searchTree(5) is null); assert(tree1.searchTree(4) !is null); } When I run the unittest the compiler complains: cannot implicitly convert expression of type const(Tree!string)* to Tree!string* Run link: https://run.dlang.io/is/b76DND Why does this happen? If I correctly understand what you are trying to do the answer is - in D const is transitive (unlike the C++ where it isn't). And in your searchTree() method you are basically trying to escape that constness. You can change the signature to return const(Self)*, or maybe add non-const overload depending on your needs. Don't even think about casting away const with `return cast(Self*) ` as this UB in D, and it will bite you somewhere later because compiler might rely on const for optimization.
`this` template params for struct not expressing constness.
Hi, as far as I understand, the `this` template parameter includes constness qualifiers as seen in https://ddili.org/ders/d.en/templates_more.html To apply this I have this following struct: module bst; struct Tree(T) { T item; Tree!T* parent, left, right; this(T item) { this.item = item; } Self* searchTree(this Self)(auto in ref T item) const { if ( is null) return null; if (this.item == item) return return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } } unittest { auto text1 = "Hello", text2 = "World"; auto tree2 = Tree!string(text1); assert(tree2.searchTree(text2) is null); assert(tree2.searchTree(text1) !is null); auto tree1 = Tree!int(4); assert(tree1.searchTree(5) is null); assert(tree1.searchTree(4) !is null); } When I run the unittest the compiler complains: cannot implicitly convert expression of type const(Tree!string)* to Tree!string* Run link: https://run.dlang.io/is/b76DND Why does this happen?
Re: non-constant expression while initializing two dim array
On Monday, 8 June 2020 at 06:37:18 UTC, tirithen wrote: How can I initialize my two dimensional array? When I try to run the code below I get the error: Error: non-constant expression ["user":[cast(Capability)0], "administrator":[cast(Capability)1]] Code: enum Capability { self, administer } alias Capabilities = immutable Capability[]; private Capabilities[string] roleCapabilities = [ "user" : [Capability.self], "administrator" : [Capability.administer] ]; I have tried adding more const and immutable prefixes but it still gives me the same error. The goal is that roleCapabilities should be an immutable/const two dimensional array. What you declare here is not a two dim array it's an associative array. Associative array implementation have limitations. To initialize one that doesn't have const expr as key you can use a static module constructor: --- enum Capability { self, administer } alias Capabilities = immutable Capability[]; private Capabilities[string] roleCapabilities; static this() { roleCapabilities = [ "user" : [Capability.self], "administrator" : [Capability.administer] ]; } --- which is done at runtime, just before the D main() get executed. Notes: 1. You can also use a function containing a switch statement instead of an assoc array. 2. the other way would work because it would be a static array, the enum member giving an integer index: --- enum Capability { self, administer } alias Capabilities = immutable Capability[]; private string[Capability.max + 1] roleCapabilities = [ Capability.self : "user", Capability.administer : "administrator", ]; --- but I suppose that is different.
Re: how to append (ref) int[] to int[][]?
On Monday, 8 June 2020 at 06:42:44 UTC, Simen Kjærås wrote: Arrays (technically, slices) in D are essentially this struct: struct Array(T) { T* ptr; size_t length; // operator overloads } So when you have int[][], each element of the outer array is an Array!int. These, as simple structs, are copied about, so that changing one does not change another. Thank you for the reply, I think this explanation should be added to the top of https://dlang.org/spec/arrays.html Then people (esp with C/C++ background) can easily understand D's array behavior.
Re: how to append (ref) int[] to int[][]?
On Monday, 8 June 2020 at 06:13:36 UTC, mw wrote: Hi, I have this program: import std.stdio; void f(ref int[] arr) { arr ~= 3; } void main() { int[][] arrs; int[] arr; foreach (i; 0 .. 3) { arr = new int[0]; arrs ~= arr; //(a) [[], [], []] f(arr); // arrs ~= arr; //(b) [[3], [3], [3]] } writeln(arrs); } This program will print out [[], [], []]. If I comment out (a), and use (b), it will print out [[3], [3], [3]] So based on this behavior, looks like "~=" will append a copy of `arr`; but what I really want in (a) is append `ref arr` and output [[3], [3], [3]], i.e. the real `arr` be appended instead of its copy. I have to say this semantics surprised me. I tried to change arrs' decl to: (ref (int[]))[] arrs; // the intended semantics I want But I got compiler error out: "found ( when expecting function literal following ref". 1) I'm wondering how to achieve what I want? and 2) why "~=" here will append a copy rather than the real `arr` itself to arrs? Arrays (technically, slices) in D are essentially this struct: struct Array(T) { T* ptr; size_t length; // operator overloads } So when you have int[][], each element of the outer array is an Array!int. These, as simple structs, are copied about, so that changing one does not change another. The simple solution here is to call f not on arr, but on arrs[$-1] (the last element of arrs). If that is not possible you will need arrs to be an int[]*[]. -- Simen
non-constant expression while initializing two dim array
How can I initialize my two dimensional array? When I try to run the code below I get the error: Error: non-constant expression ["user":[cast(Capability)0], "administrator":[cast(Capability)1]] Code: enum Capability { self, administer } alias Capabilities = immutable Capability[]; private Capabilities[string] roleCapabilities = [ "user" : [Capability.self], "administrator" : [Capability.administer] ]; I have tried adding more const and immutable prefixes but it still gives me the same error. The goal is that roleCapabilities should be an immutable/const two dimensional array.
how to append (ref) int[] to int[][]?
Hi, I have this program: import std.stdio; void f(ref int[] arr) { arr ~= 3; } void main() { int[][] arrs; int[] arr; foreach (i; 0 .. 3) { arr = new int[0]; arrs ~= arr; //(a) [[], [], []] f(arr); // arrs ~= arr; //(b) [[3], [3], [3]] } writeln(arrs); } This program will print out [[], [], []]. If I comment out (a), and use (b), it will print out [[3], [3], [3]] So based on this behavior, looks like "~=" will append a copy of `arr`; but what I really want in (a) is append `ref arr` and output [[3], [3], [3]], i.e. the real `arr` be appended instead of its copy. I have to say this semantics surprised me. I tried to change arrs' decl to: (ref (int[]))[] arrs; // the intended semantics I want But I got compiler error out: "found ( when expecting function literal following ref". 1) I'm wondering how to achieve what I want? and 2) why "~=" here will append a copy rather than the real `arr` itself to arrs? Thanks.