Re: DlangUI Layout Justification
On Friday, 7 April 2023 at 17:13:58 UTC, Adam D Ruppe wrote: On Friday, 7 April 2023 at 15:52:02 UTC, Ali Çehreli wrote: I don't know how relevant it is but there is also Hipreme Engine that supports Android: [...] One library can help with both games and guis but it is unlikely to be a complete solution for either, certainly not both. Wow, what a great comparison, Adam! I've worked on GUIs, but never on games... and often wondered about this. Maybe you can copy+paste the whole thing as a topic on your blog ...? This comparison deserves *not* to fade into oblivion as is the typical fate of most forum discussions.
Re: My vibe-d test app is crashing on Windows
On Monday, 13 February 2023 at 13:12:23 UTC, Steve wrote: The app is just a test echo server. JSON sent in the body of a POST request is echoed back to the client. On Pop!_OS it works fine but on Windows it responds, there's a delay of about 10 seconds and then it crashes with the error: ``` Error Program exited with code -1073741819 ``` Here's the code: ```d import vibe.vibe; import std.json, std.stdio; void main() { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; auto router = new URLRouter; router.get("*", serveStaticFiles("public/")); router.post("/", &onPost); auto listener = listenHTTP(settings, router); scope (exit) { listener.stopListening(); } logInfo("App listening at http://127.0.0.1:8080/";); runApplication(); } static string handlePost(string req) { return req; } void onPost(HTTPServerRequest req, HTTPServerResponse res) { try { auto jsr = async(&handlePost, req.json.toString()).getResult(); res.contentType("application/json; charset=utf-8"); res.writeBody(jsr); } catch (Exception e) { res.contentType("text/plain; charset=utf-8"); res.writeBody(e.msg); } } ``` Also when you launch/build the app with dub there's a shed load of deprecation warnings, e.g.: ``` \Local\dub\packages\vibe-d-0.9.5\vibe-d\stream\vibe\stream\wrapper.d(334,23): Deprecation: reference to local variable `this` assigned to non-scope parameter `bytes` calling `writeToStream` ``` I'm a D newbie so it's quite possibly something I'm doing wrong ... The -1073741819 error is OxC005 in hex. And C005 on Windows is a access violation exception, indicating that you are trying to access memory that doesn't belong to your process. Possibly a 'buffer overrun' access exception - but I'm not sure in this case. Unfortunately I'm not experienced with vibe at all - so I can't help with your code. Just google 'Windows error C005' for more info.
Re: pointer escaping return scope bug?
On Friday, 25 November 2022 at 14:07:28 UTC, ShadoLight wrote: On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` [snip] I don't grok how `lf` can survive the local scope. Or am I missing something? Perhaps because the local scope is not pushed as a separate (anonymous) function on the stack... if true then, yes, then `lf` will indeed have the same physical lifetime as main (and `p`)...? On the other hand, if you add a destructor to `LockedFile`, it will be invoked at the end of the local scope, not the end of main. I find it a bit confusing what the term "lifetime" should pertain to in the case of variables declared inside a local scope inside a function - destructor invocation or physical existence of the variable on the stack? But this has no bearing on the heap allocation and the lifetime of `p` in the example.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 15:00:16 UTC, Paul Backus wrote: On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven wrote: Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something. I think this is intended behavior, because you *do* get an error if you replace `new int` with a pointer to a stack variable; e.g., int local; auto lf = LockedFile(&local); The `return scope` qualifier on the method does *not* mean "the return value of this method is `scope`". It means "this method may return one of this object's pointers, but does not allow them to escape anywhere else." In other words, it lets the compiler determine that the return value of `lf.fp` has *the same* lifetime as `lf` itself. Since, in your example, `lf` has global lifetime, the compiler deduces that `lf.fp` also has global lifetime, and therefore there is nothing wrong with assigning it to `p`. I follow your rationale, but for the life of me I cannot see how `lf` _"has global lifetime"_. Looks to me like `lf` is a value instance of the `LockedFile` struct (so on the stack) in a local scope inside main. I fully agree that the above code is not problematic, but isn't that because `p` is declared outside this local scope, and the allocation that happens inside the local scope (in the `lf` constructor) is on the heap, so the allocation (now assigned to `p`) survives the end of the local scope (and the end of the life of `lf`) since it is `p` that has global lifetime? I don't grok how `lf` can survive the local scope. Or am I missing something?
Re: How to link a msvcr120.dll in an inverse recursive way after a Windows .exe binary deployment
On Tuesday, 6 September 2022 at 04:59:49 UTC, Mike Parker wrote: On Tuesday, 6 September 2022 at 04:36:55 UTC, ShadoLight wrote: True. In that case just distribute the DLL (taken from the DMD bin folder) alongside the HelloWorld EXE so that both reside in the same folder on the target computer. The proper way to do this is to ship the correct version of the Visual C++ redistributable installer and run it as part of the application install process: https://docs.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170 Sure. But the OP seems to indicate that he doesn't have administrative privileges on the machines they wish to distribute and test his HelloWorld example. I don't know if you can run an installer without administrative privileges - at least not if you want to write to Program Files / Program Files (x86), modify the Registry, environment variables, etc. I'm not even sure if you can create a folder on Windows 10 without administrative rights without resorting to some tricks. I've never required that - and would think that the IT department (that handles installs and updates on their organization's computers) should have an admin account on all of them. My take was that he can simply copy the EXE and associated DLLs to an existing folder on the target machine if he just want to test it running on a non-developer machine. Making an installer is another mini-project by itself .. not sure if he wants to be burdened with such a step simply to resolve his DMD issue. But your redistributable installer link is indeed the proper way.
Re: How to link a msvcr120.dll in an inverse recursive way after a Windows .exe binary deployment
On Monday, 5 September 2022 at 07:02:53 UTC, BoQsc wrote: The problem is, D Language Compiler is not included along the Windows Operating System. No compiler is included natively with the Windows OS. Not even Microsoft's. Neither msvcr120.dll is included along the Windows Operating System. You have to download it. No other way. Or... you download the DMD installer which conveniently include it for you. How can you download it, if your .exe binary that has the functionality to download it, cannot even be started due to msvcr120.dll not existing on the operating system. I don't understand this. You need DMD to build your EXE. I suppose you have this since your question is specifically about DMD. If that is the case you have the DLL you need. Copy the DLL to C:\Windows\System32\ It required administrator privilegies and this is only a HelloWorld example of the D language deployed on computers, where the D language is yet to be installed. True. In that case just distribute the DLL (taken from the DMD bin folder) alongside the HelloWorld EXE so that both reside in the same folder on the target computer. If you don't have administrative priveleges you cannot modify the PATH on the target computer either, so this is the only way. That is anyway quite standard under Windows - if you search for msvcr*.dll on any Windows machine you'll find lots of copies co-located with the EXEs that use them (using the version that came with the specific version of Visual Studio they were using to build the EXE - for example msvcr90.dll). These DLLs are simply the Visual Studio C/C++ Runtime distributed with Visual Studio.
Re: How to link a msvcr120.dll in an inverse recursive way after a Windows .exe binary deployment
On Sunday, 4 September 2022 at 15:16:47 UTC, BoQsc wrote: **Folder structure** .\msvcr120.dll .\folder1\HelloWorld.exe .\folder2\HelloWorld.exe You don't need to do this. msvcr120.dll is already shipped with the DMD compiler at [DMD-install-folder]\windows\bin64\msvcr120.dll. (It is also in [DMD-install-folder]\windows\bin). You can access it directly from there. When you run your EXE... the OS looks for the DLL in the same folder of the EXE- if it cannot find it it looks in the folders specified in your PATH. You can test if this is the case by executing 'where msvcr120.dll' at a DOS console command prompt. If the DLL is reachable in any folder in your PATH environment variable these specific path(s) will be displayed. In this case you don't need to do anything - the EXE should be able to run and load the DLL. The fact that you get this error indicate this is not the case. You can do 1 of the following 2 things: - add your DMD bin64 (or bin) path to the PATH environment variable. --or-- - Copy the DLL to C:\Windows\System32\ - that will for sure already be in your PATH so you don't need to modify your PATH environment variable.
Re: What are virtual functions?
On Wednesday, 14 April 2021 at 14:06:18 UTC, FeepingCreature wrote: On Wednesday, 14 April 2021 at 13:43:20 UTC, Berni44 wrote: [..] Covariance is related ... [..] The opposite (contravariance) happens ... [..] Nice answer but, just to be clear - D only supports covariance on return types at the moment, and doesn't support contravariance on parameters, right? I remember contravariance being periodically requested in the past but, AFAICR, it has not been implemented, right? A quick search through the forums didn't turn anything up either... and this does not compile: ``` class A {} class B : A {} class Y { public void bar (B b) {} } class X : Y { public override void bar (A a){} } ```
Re: F*cked by memory corruption after assiging value to associative array
On Monday, 25 January 2021 at 17:11:37 UTC, frame wrote: On Monday, 25 January 2021 at 16:54:42 UTC, vitamin wrote: On Monday, 25 January 2021 at 16:44:40 UTC, frame wrote: On Monday, 25 January 2021 at 16:14:05 UTC, vitamin wrote: Yes, I directly calling on every function that returns an object: T fun(T)(T object) { GC.addRoot(cast(void*) object); } ... extern (C) export SomeObject bar() { return fun(new SomeObject); } Just to confirm... I assume you just neglected to show the line in fun template function that returns the object, right? Like... T fun(T)(T object) { GC.addRoot(cast(void*) object); return object; }
Re: Range of dub package versions
On Monday, 28 December 2020 at 23:49:02 UTC, rikki cattermole wrote: $ dub upgrade [..] Unless you change the version invalidating it, it most likely won't upgrade by itself. Thanks Rikki - that explains it and, indeed, worked perfectly. Thanks!
Range of dub package versions
I can build my app using dub, which has a dependency on the particular version of dlangui that was available when I originally created the project: "dependencies": { "dlangui": "~>0.9.182", ...etc.. }, I've recently noticed that the dlangui package is now on v0.9.186. According to [1] this means: "Restrict to a certain minor version: "~>2.2.13", equivalent to ">=2.2.13 <2.3.0"" which I understood means that a 'dub build' would automatically download and use this latest version (well, up to v0.10.0 anyway). But I probably misunderstood this - since this does not happen and a 'dub build' still reports: dlangui 0.9.182: target for configuration "default" is up to date. Is this behaviour correct? If it is, then does this not imply that one still have to manually track and update the json file each time a dependency package is updated (if you want to stick with the latest version)? Note that I do understand that, if I had v0.9.186 package on my machine, the same json file (that specifies "~>0.9.182") will still work and actually use this version of the package. But the thing is, how would I get v0.9.186 on my machine except by doing a explicit 'dub fetch/add' step? What then is the advantage to the "~>0.9.182" syntax compared with simply specifying the actual version (as in "dlangui": "==0.9.182" if it anyway boils down to a tracking dependency versions manually? What am I missing? [1] https://dub.pm/package-format-json.html#version-specs
Re: Why private methods cant be virtual?
On Tuesday, 22 September 2020 at 11:39:31 UTC, Daniel Kozak wrote: On Tue, Sep 22, 2020 at 1:30 PM ShadoLight via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com> wrote: This is not really "overriding", it is more akin to "overloading" No it is not overloading, overloading is when you have more methods with same name and differents params. It is overriding Which is why I said it is "is more akin to "overloading"" i.e. what I meant is that the behaviour is kind-of "similar" to overloading in your example. I did not mean it was classical overloading. The thing is that, if the base class method is non-virtual, calling it "overriding" is confusing and somewhat misleading - all the derived class does is hide (or "shadow" if you like) the base class method. It is also not polymorphic I did not say otherwise :-) Granted, but your example is confusing in the light that the OP specially asked about virtual and polymorphic behaviour.
Re: Why private methods cant be virtual?
On Tuesday, 22 September 2020 at 10:23:08 UTC, Daniel Kozak wrote: On Tue, Sep 22, 2020 at 11:06 AM claptrap via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com> wrote: "Functions marked as final may not be overridden in a derived class, unless they are also private" So final private functions can be overriden? It seems not, but the sentence is definitely confusing if not just plain wrong. Yes they can, if you have class A in one module and class B in another module this will work: //a.d class A { private final void overrideFun() { import std.stdio : writeln; writeln("A::overrideFun"); } } //b.d import a; class B : A { void overrideFun() { import std.stdio : writeln; writeln("B::overrideFun"); } } // main.d import b; void main(string[] args) { B b = new B; b.overrideFun; } This is not really "overriding", it is more akin to "overloading". It is also not polymorphic i.e. this will call A::overrideFun. A b = new B; b.overrideFun;
Re: Alternative to friend functions?
On Thursday, 20 February 2020 at 08:02:48 UTC, Bienlein wrote: On Tuesday, 18 February 2020 at 12:43:22 UTC, Adnan wrote: What is the alternative to C++'s friend functions in D? module stable_matching; alias FemaleID = int; alias MaleID = int; class Person { string name; int id; } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Female : Person { this(string name = "Unnamed Female") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Husband(uint N) : Male { FemaleID engagedTo = -1; const FemaleID[N] preferences; this(FemaleID[N] preferences) { this.preferences = preferences; } } class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to } class MatchPool(uint N) { Husband!N[N] husbands; Wife!N[N] wives; } I would make Husband and Wife subclasses of a common abstract superclass Spouse that declares the engagedTo var. The Spouse superclass would also be the place where to put the engage method. What is different for males and females you can redefine in the respective subclass. But where in that inheritance hierarchy will you slot the Spouse class in? You don't have multiple inheritance in D, so are you thinking along these lines?: class Person {..} class Spouse : Person {..} class Male : Spouse {..} class Female : Spouse {..} That implies every Male and Female 'is a' Spouse which, feels a bit clunky to me. Maybe a better design for your idea is to make Spouse an interface; something along these lines: class Person {..} interface Spouse {void engage(..);} class Male : Person, Spouse {..} class Female : Person, Spouse {..} Then, as you say, the respective engage(..) implementations are done in the Male/Female subclass. Maybe you can even declare a winArgument(..) method returning a bool in the Spouse interface. For the Male class the implementation will be real easy: just return false! [Disclaimer]: Last paragraph not to be taken seriously!
Re: Template Usage with Eponymous Trick
On Sunday, 2 February 2020 at 23:48:45 UTC, Paul Backus wrote: On Sunday, 2 February 2020 at 23:39:10 UTC, ShadoLight wrote: But, my question was if this was avoidable if braces were not optional. Paul's answer was that non-optional braces will not make... alias a = S!(int); ... non-ambiguous, but I still don't get that based on the above results. [..] If the behavior were changed as you have previously proposed, so that `S!(int)` could refer *either* to the eponymous struct *or* the template instance, then the alias declaration would become ambiguous. Again, this would be true whether or not you used braces. Ok, I get it. Thanks.
Re: Template Usage with Eponymous Trick
On Sunday, 2 February 2020 at 18:30:17 UTC, Steven Schveighoffer wrote: Thanks for taking the time to explain. However, when I tested my results does not seem to match your explanation. First, note that: struct S(T) {} is *exactly* equivalent to (in fact, you can write it this way, and it works exactly the same): template S(T) { struct S {} } Yes, agreed. So does S!int refer to the template instantiation (which is not a type) or the eponymous S struct inside the template (which is a type)? This was Paul's point. I get what you are trying to say, but testing actually shows S!int is already a type in the eponymous case (but not in the classical case). If I do as in Paul's example... template S(T) { struct S {T x;} } // Should this assertion pass or fail? static assert(is(S!(int))); //PASS void main() { auto a = S!(int)(3); writeln(typeof(a).stringof); } ... it actually compiles and the assertion passes (and prints S!int as the type), so it seems the eponymous template instantiation already created its eponymous struct as well, no? But I guess that in terms of 'short-hand' syntax it actually makes sense since it is an eponymous template and, as you/Paul explained previously, it should only be invoked in this way. In contrast, for the non-eponymous case template R(T) { struct Q {T x;} } // Should this assertion pass or fail? //static assert(is(R!(int))); //FAIL void main() { auto b = R!(int).Q(3); writeln(typeof(b).stringof); } ... now the assertion fails as expected, but the type printed is simply Q. So we actually have this: template S(T) { struct S {} } template R(T) { struct Q {} } static assert(is(S!(int)) == true); //PASS static assert(is(R!(int)) == false); //PASS I can understand (as @MoonlightSentinel's example showed), that optional braces can make this ambiguous and that is the current situation. But, my question was if this was avoidable if braces were not optional. Paul's answer was that non-optional braces will not make... alias a = S!(int); ... non-ambiguous, but I still don't get that based on the above results.
Re: Template Usage with Eponymous Trick
On Sunday, 2 February 2020 at 16:23:42 UTC, Paul Backus wrote: [..] No, it would still be ambiguous: struct S(T) {} alias a = S!(int); // Should this assertion pass or fail? static assert(is(a)); Sorry, I don't get it. AFAICS 'is(a)' should return true (since a is an alias for a full type here) - and braces being compulsory or optional does not affect this. AFAICS: struct S(T) {} alias a = S!(int); alias b = S; // Should this assertion pass or fail? static assert(is(a)); //PASS static assert(is(b)); //FAIL But I don't see how braces will affect this. Can you explain?
Re: Template Usage with Eponymous Trick
On Friday, 31 January 2020 at 15:37:06 UTC, Steven Schveighoffer wrote: On 1/30/20 9:10 AM, ShadoLight wrote: but to give you some historical perspective... [..] It was actually much more restrictive before -- e.g. in order to do an eponymous template, you could have no other members in the template. Thanks for the historical perspective Steve. Appreciated. When you refer to 'other members' in the eponymous template, I notice that they are indeed allowed, but are effectively hidden (if they have a different name from the template name) inside the eponymous template, correct? For example, this works fine in 'classical' template style - all members are 'public' and accessible: template bar(T) { T z; //Allowed... void b1(T x){z+=x;} //Allowed... void b2(T x){z-=x;} //Allowed... } void main() { bar!(int).b1(4);//Works.. writeln(bar!int.z); //Works.. bar!(int).b2(5);//Works.. writeln(bar!int.z); //Works.. } For eponymous templates, only members with the overloaded template identifier are accessible 'from the outside'. template foo(T) { T z; //Allowed... void foo(T x){f1(x);} //Allowed... T foo(){return z;}//Allowed... void f1(T x){z+=x;} //Allowed... } void main() { foo(3); //Works.. foo(4); //Works.. writeln(foo!int.z); //onlineapp.d(21): Error: no property z for type int foo!int.f1(3); //onlineapp.d(21): Error: no property f1 for type int writeln(foo!int()); //Works.. } So the eponymous template invocation has to use the eponymous 'trick' and only overloaded members are accessible. Not bad and definitely an improvement , but I still find the inconsistency jarring... IIUC this 'ambiguity' would have been avoidable if template argument braces were not optional, right? I do know this horse has bolted, but personally I think it D made a mistake to make the braces on compile-/run-time arguments on template/function invocation optional in the zero/one argument case. It is not even completely symmetric between compile- and run-time: in compile time you can leave the braces off in the case of zero and one arguments, but for run-time only for zero arguments. For want of the effort to type 2 braces, a fair bit of complexity and some inconsistency has been introduced into the language. And I remember that it actually made code harder to read when I started out in D, not easier. I support the dropping of the braces in the case of property functions, but that use case is quite clear-cut and I think easy to handle based on the @property annotation.
Re: Template Usage with Eponymous Trick
On Thursday, 30 January 2020 at 20:42:02 UTC, Paul Backus wrote: On Thursday, 30 January 2020 at 15:14:43 UTC, ShadoLight wrote: [..] would make the language grammatically ambiguous... OK, understood. Thank you.
Re: Template Usage with Eponymous Trick
On Thursday, 30 January 2020 at 20:00:05 UTC, MoonlightSentinel wrote: On Thursday, 30 January 2020 at 17:00:08 UTC, ShadoLight wrote: [..] ...your proposed change it would be ambigous ... Ok, that makes sense - I did not consider the impact of the optional empty braces. Thank you.
Re: Template Usage with Eponymous Trick
On Thursday, 30 January 2020 at 16:16:48 UTC, MoonlightSentinel wrote: On Thursday, 30 January 2020 at 15:14:43 UTC, ShadoLight wrote: [...] From my POV is void foo(T)() { ... } just a shorthand notation for... Agreed. My question though is should the 'shorthand' notation _replace_ the 'longhand' notation, or be available _in addition_ to the 'longhand' notation in the eponymous case (so the eponymous notation is just 'syntax sugar' if you will). If you had... template foo(T) { bar(){..} } ...you have no choice but to use foo!(int).bar()- (where T is 'int'). So, I'm asking, in the eponymous case, should... template foo(T) { foo(){..} } force you to use foo!(int)() instead (as is currently the case), or should foo!(int).foo() also still be acceptable/available? For consistency's sake I think it should be but, if there is some reason why this is not technically possible/advisable, I was hoping someone would enlighten me. And, in that case some of the examples in the documentation needs fixing.
Re: Template Usage with Eponymous Trick
On Thursday, 30 January 2020 at 14:22:11 UTC, Paul Backus wrote: On Thursday, 30 January 2020 at 14:10:38 UTC, ShadoLight wrote: ...but in the 'classical' default template style, so I would have thought the template_name!(compile_time_args).function_name(run_time_args) style would still work, even if the template and function names are identical. If this is in fact now the intended behavior, then there are some places where the documentation are in error. [1]: https://dlang.org/spec/template.html#variadic-templates Eponymous templates are documented here: https://dlang.org/spec/template.html#implicit_template_properties This specific behavior is documented in the first paragraph below that heading, which reads as follows: If a template contains members whose name is the same as the template identifier and if the type or the parameters type of these members include at least all the template parameters then these members are assumed to be referred to in a template instantiation Yes, the behavior is described but not that it is in fact the _only_ way that an eponymous template can in fact be instantiated. I think this behavior will be surprising for someone new to D. For eponymous templates you actually have the short-hand declarative style as well... void foo(S, T)(S s, T t) {} ..ok, needs to call with... foo!(int, int) (1, 2); ...or even just... foo(1, 2); ...and your template parameters will be deduced. This is at least kind-of intuitive. But now if you declare the template in the fully standard way: template foo(S, T) { void foo(S s, T t) {} } ..and you call it in the completely standard way (as you would have in fact been required if template identifier and member were differently named)... foo!(int, int).foo(1, 2); ..it not only does _not_ compile, but gives you an error: onlineapp.d(12): Error: function onlineapp.foo!(int, int).foo(int s, int t) is not callable using argument types () ...where foo!(int, int).foo(int s, int t) is clearly a match! I really like the eponymous template trick and all that, but this did catch me by surprise -I did not realize that the eponymous template style in fact invalidates the 'classic' template invocation style: it is one or the other. I was somehow under the mistaken impression that you could still revert to the classic style, even if your template identifier and member identifier were identical. Is there a technical reason for this limitation? Why are the 'classical' invocation style not allowed for eponymous templates as well? It seems somewhat arbitrary - note that inner/outer functions does not have this limitation - the fllowing is legal and compiles (and does not lead to infinite recursion): int foo(int a, int b) { int foo(int x, int y) {return x+y;} return foo(a, b); } void main() { int z = foo(2, 4); }
Re: Template Usage with Eponymous Trick
On Thursday, 30 January 2020 at 14:10:38 UTC, ShadoLight wrote: Taking this example from documentation page on 'Template Sequence Parameters' [1]: [...] Tested on https://run.dlang.io
Template Usage with Eponymous Trick
Taking this example from documentation page on 'Template Sequence Parameters' [1]: import std.stdio; template print(args...) { void print() { writeln("args are ", args); // args is a ValueSeq } } template write(Args...) { void write(Args args) // Args is a TypeSeq // args is a ValueSeq { writeln("args are ", args); } } void main() { print!(1,'a',6.8).print();// prints: args are 1a6.8 write!(int, char, double).write(1, 'a', 6.8); // prints: args are 1a6.8 } This fails to compile with: onlineapp.d(22): Error: template onlineapp.print cannot deduce function from argument types !()(void), candidates are: onlineapp.d(3):print(args...)() onlineapp.d(23): Error: function onlineapp.write!(int, char, double).write(int _param_0, char _param_1, double _param_2) is not callable using argument types () onlineapp.d(23):missing argument for parameter #1: int _param_0 Fixing the error is simply to use 'simplified' template calling convention for templates based on the 'Eponymous Trick': print!(1,'a',6.8)();// prints: args are 1a6.8 write!(int, char, double)(1, 'a', 6.8); // prints: args are 1a6.8 Why does the 'classical' template calling convention not work anymore in this case? (if the template name and function name are different it obviously still works). Note the templates were not defined in the simplified 'Eponymous Trick' style i.e.: void print(args...)() { writeln("args are ", args); // args is a ValueSeq } void write(Args...)(Args args) // Args is a TypeSeq // args is a ValueSeq { writeln("args are ", args); } ...but in the 'classical' default template style, so I would have thought the template_name!(compile_time_args).function_name(run_time_args) style would still work, even if the template and function names are identical. If this is in fact now the intended behavior, then there are some places where the documentation are in error. [1]: https://dlang.org/spec/template.html#variadic-templates
Re: How load icon from resource using LoadImage?
On Sunday, 5 January 2020 at 13:52:27 UTC, JN wrote: On Sunday, 5 January 2020 at 13:33:35 UTC, Marcone wrote: [snip] By the way, have you managed to add the res file into the binary? My understanding is that the res file should be added into the exe file by the rc command before it can be used. Sort of correct... but not strictly correct. Typically the resource compiler (such as Microsoft's rc.exe) compiles xyzfile.rc into xyzfile.res. xyzfile.res is then added into the exe by the linker during linking.
Re: How to use ResizerWidget in Dlangui app..?
On Thursday, 2 January 2020 at 05:24:33 UTC, Rémy Mouëza wrote: On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote: Hi, I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing. I ran into the same issue. The resizeEvent callback is not implemented yet. Below is my custom implementation. /** A completed resizer widget. As of 2016-12-30, the ResizerWidget does not work out of the box. This class implement the missing piece. */ class Resizer : ResizerWidget { /// Default initialization. this () { super (); initResizeCb (); } /// Create with ID parameter. this (string ID, Orientation orient = Orientation.Vertical) { super (ID, orient); initResizeCb (); } /// Initialize the resize on drag behaviour callback. protected void initResizeCb () { this.resizeEvent = (ResizerWidget source, ResizerEventType event, int currentPosition) { if (event != ResizerEventType.Dragging) { return; } if (_orientation == Orientation.Horizontal) { auto delta = _previousWidget.width - currentPosition; auto pw= max (0, _previousWidget.width - delta); auto mw= max (0, _nextWidget.width + delta); _previousWidget .minWidth (pw) .maxWidth (pw); _nextWidget .minWidth (mw) .maxWidth (mw); } else if (_orientation == Orientation.Vertical) { auto delta = _previousWidget.height - currentPosition; auto pw= max (0, _previousWidget.height - delta); auto mw= max (0, _nextWidget.height + delta); _previousWidget .minHeight (pw) .maxHeight (pw); _nextWidget .minHeight (mw) .maxHeight (mw); } parent.requestLayout (); }; } } Remy, just a quick note to say thank you again! I had to make a small adjustment to make the Resizer class completely generic for all cases, but I can only guess you did not need this as your use case probably had the ResizerWidget parent as the outermost widget. The issue is that the currentPosition argument in the resizeEvent handler is in terms of the application window, and not in terms of the ResizerWidget parent. So, if you have another widget above the ResizerWidget parent (in the Orientation.Vertical case) or to the left of the ResizerWidget parent (in the Orientation.Horizontal case), you have a small offset issue. The same applies if you have margins or padding on the ResizerWidget parent (or any of its parent(s)). Anyway, the fix is quite trivial: /// Initialize the resize on drag behaviour callback. protected void initResizeCb () { this.resizeEvent = delegate(ResizerWidget source, ResizerEventType event, int currentPosition) { if (event != ResizerEventType.Dragging) { return; } int delta; int pw; int mw; int localPos; if (_orientation == Orientation.Horizontal) { localPos = currentPosition - parent.left; delta = _previousWidget.width - localPos; pw= max (0, _previousWidget.width - delta); mw= max (0, _nextWidget.width + delta); _previousWidget .minWidth (pw) .maxWidth (pw); _nextWidget .minWidth (mw) .maxWidth (mw); } else if (_orientation == Orientation.Vertical) { localPos = currentPosition - parent.top; delta = _previousWidget.height - localPos; pw= max (0, _previousWidget.height - delta); mw= max (0, _nextWidget.height + delta); _previousWidget .minHeight (pw) .maxHeight (pw); _nextWidget .minHeight (mw) .maxHeight (mw); } parent.requestLayout (); }; } }
Re: How to use ResizerWidget in Dlangui app..?
On Thursday, 2 January 2020 at 05:24:33 UTC, Rémy Mouëza wrote: On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote: Hi, I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing. I ran into the same issue. The resizeEvent callback is not implemented yet. Below is my custom implementation. [snip] OK, I suspected as much. But thanks a lot Rémy! You are saving me a lot of work - much appreciated!
Re: How to use ResizerWidget in Dlangui app..?
On Wednesday, 1 January 2020 at 10:52:02 UTC, Ron Tarrant wrote: On Monday, 30 December 2019 at 23:32:37 UTC, ShadoLight wrote: dragging with the left mouse button does nothing. Window window = Platform.instance.createWindow("DlangUI example", null); I'm not familiar with this toolkit, but my guess is that you didn't pass in a `flags` value and therefore you aren't using the appropriate overload of the createWindow() function to achieve what you're after. The following is from the DLangUI GitHub site (https://github.com/buggins/dlangui/wiki/Getting-Started). Take a look at the third argument: Window createWindow( dstring windowCaption, // window caption Window parent, // parent window, pass null for main (first) window. uint flags = WindowFlag.Resizable, // various flags - bit fields from WindowFlag enum values uint width = 0,// initial window width uint height = 0// initial window height ); Thanks for the reply, Ron. Yes, as you say WindowFlag.Resizable is the default value for the 'flags' argument in the createWindow call, so that was the setting I had. But the problem is actually not in resizing the full app window (that actually works - including keeping the relative proportions of the widget children sizes), but rather in resizing 2 widgets that are separated by a ResizerWidget inside the app window. The app window size should actually not be affected since, as 1 widget on one side of the ResizerWidget shrinks by N pixels in height or width (depending on the orientation of the ResizerWidget), the opposite widget should grow by the same N pixels in height/width, leaving the parent size unaffected. I can see that is actually what is coded, but it is not working when I run the app. But I thought you may be on to something and I should check if children widgets of the app window inherits some settings from the parent, so I checked the WindowFlag flags. According to [1] you can have: - Fullscreen - Modal - Resizable However, checking the code there are additional options: /// window creation flags enum WindowFlag : uint { /// window can be resized Resizable = 1, /// window should be shown in fullscreen mode Fullscreen = 2, /// modal window - grabs input focus Modal = 4, /// measure window size on window.show() - helps if you want scrollWindow but on show() you want to set window to mainWidget measured size MeasureSize = 8, /// window without decorations Borderless = 16, /// expand window size if main widget minimal size is greater than size defined in window constructor ExpandSize = 32, } So it looks like the documentation isn't completely up to date either. Anyway, I also tried to pass WindowFlag.Resizable | WindowFlag.MeasureSize as flags argument in the call to createWindow, but it did not help. I was hoping for a quick answer on the forum from someone who has run into the same, but I think I'm going to need to dig into dlangui code to figure out what is going wrong. [1]: http://buggins.github.io/dlangui/ddox/dlangui/platforms/common/platform/WindowFlag.html
How to use ResizerWidget in Dlangui app..?
Hi, I suspect I'm missing something obvious, but ResizerWidget is not working for me on Windows - it shows the 'dragging'-cursor when hovering the mouse on the ResizerWidget, but dragging with the left mouse button does nothing. Reduced very simple example: ///app.d import dlangui; import gui; mixin APP_ENTRY_POINT; /// entry point for dlangui based application extern (C) int UIAppMain(string[] args) { // create window Window window = Platform.instance.createWindow("DlangUI example", null); //Make main layout auto mainGui = new GuiHandler(); window.mainWidget = mainGui.makeGui(window); // show window window.show(); // run message loop return Platform.instance.enterMessageLoop(); } /// gui.d import dlangui; class GuiHandler : ResizeHandler { Widget makeGui(Window w) { //Make main layout auto vlayout = new VerticalLayout(); vlayout.margins = 20; vlayout.padding = 10;ets vlayout.backgroundColor = 0xC0; vlayout.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); // Layout for editors auto editorsLayout = new LinearLayout(); editorsLayout.orientation = Orientation.Vertical; //Make edit + trace windows auto editor = new EditBox(); editorsLayout.addChild(editor); auto resizer = new ResizerWidget(); // resizer.resizeEvent.connect(this); //Connect for handling events in onResize. editorsLayout.addChild(resizer); auto tracer = new LogWidget(); editorsLayout.addChild(tracer); editorsLayout.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); vlayout.addChild(editorsLayout); return vlayout; } override void onResize(ResizerWidget source, ResizerEventType event, int currentPosition) { //Not shown... } } I searched through all the dlangui examples where ResizerWidget is used, and none of them provides any onResize event handler as shown above. But, since none of them work (symptoms exactly the same as mine), I am wondering if this is required? Also checking in DlanguiIDE - nowhere does it implements the onResize event handler for ResizerWidget either. I find this a bit odd - in none of the projects where ResizerWidget are used does it work, but none of these projects provide the onResize event handler either. Which makes me suspect it is supposed to work 'out of the box' and does not require the event handler for the basic dragging functionality - similar how resizing the whole window works without requiring that you implement it yourself in the OnResize event handler for the main Widget. Also - I can hardly believe that Vadim would have kept putting it in examples, but without it working, so I suspect some regression here if I am not doing something stupid myself (which is always possible!). There are plenty of 'deprecated' warnings when building dlangui and, since dlangui has not been updated since 2018, I'm concerned it may be breaking with new versions of the compiler. Alternatively I'm missing something elementary here..? Has anyone used ResizerWidget successfully with a recent version of the compiler on Windows? win 7 DMD32 D Compiler v2.089.1 dlangui-0.9.182
Re: How add "version.txt" Version File by Command Line or by resources.res using dmd.exe
On Tuesday, 10 December 2019 at 14:33:41 UTC, Marcone wrote: On Tuesday, 10 December 2019 at 09:48:11 UTC, ShadoLight wrote: On Tuesday, 10 December 2019 at 07:23:00 UTC, rumbu wrote: [...] To add to Rumbo's comment: to compile a *.rc to *.res file you will need a resource compiler. [...] Hi, I compile resource using windres.exe of MinGW, Can you send me the versionfile code mode to Dlang? Thank you. I'm not a 100% sure what you mean, but note there isn't a specific version "file format" (or something) that specifically applies for "dlang apps only" - the format of a *.res applies to all executables runnable on a specific platform (eg. EXEs, DLLs, etc on Windows in this case). You can use the same resource compiler to compile a *.rc to a *.res file and link this with *.objs files produced in any native language (C/C++/D/Pascal/etc) to create your EXE/DLL. Here, for example, is a kind of minimalist *.rc file from an old x86 app I did ages ago (edited to hide real names, etc): 101 ICON DISCARDABLE ".\\Resources\\someicon.ico" 205 BITMAP DISCARDABLE ".\\Resources\\somebitmap.bmp" STRINGTABLE DISCARDABLE BEGIN 3001 "This string was loaded from the resource!" END / // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 2,0,1,2 PRODUCTVERSION 2,0,0,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "My Super Co\0" VALUE "FileDescription", "Blah blah\0" VALUE "FileVersion", "2, 0, 1, 2\0" VALUE "InternalName", "MyApp\0" VALUE "LegalCopyright", "Copyright (C) 2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "MyApp.exe\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Blah blah\0" VALUE "ProductVersion", "2, 0, 0, 1\0" VALUE "SpecialBuild", "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END You can create the *.rc file by hand, but it is probably easier just to use a freely available Resource editor. The above *.rc file, IIRC, was created with XN Resource editor [1], but this was long ago and nowadays I just typically use the one that is bundled as part of Visual Studio. Linking to a *.res file such as the one above will include the resources directly in your EXE, and you then load the resources during runtime using the listed "resource identifiers" (for example 3001 for the string). Regarding the version info - it will be automatically displayed when you right-click the EXE (or DLL!) and select Properties. But this is a feature of Windoxs, not your app. To display the version info in your app (for example to display "My App v1.0.0.2" instead of just "My App" in the Title-bar) you need to do a little bit more work - you need to call the Windows API GetFileVersionInfo function [2] to extract the version info. Look at this [3] page for an example - it is in C but should be easy to adapt. [1] https://stefansundin.github.io/xn_resource_editor/ [2] https://docs.microsoft.com/en-us/windows/win32/api/winver/nf-winver-getfileversioninfoa?redirectedfrom=MSDN [3] https://stackoverflow.com/questions/940707/how-do-i-programmatically-get-the-version-of-a-dll-or-exe-file
Re: How add "version.txt" Version File by Command Line or by resources.res using dmd.exe
On Tuesday, 10 December 2019 at 07:23:00 UTC, rumbu wrote: On Sunday, 8 December 2019 at 20:50:05 UTC, Marcone wrote: I want to add version to my program. I have configurated my version file "version.txt", but I dont know how link this file to my program. If Need spec file, please send the exemple code of spec. Or is is possible add version file by dmd command line or resources. Thank you. Your version.txt file is python specific, it will not work in D. You have 2 options: - create a .res file in Visual Studio and edit it by adding a VERSIONINFO resource. - create a .rc file in any text editor adding a VERSIONINFO resource; compile it to .res using rc yourfile.rc Pass the .res file to the dmd compiler in the command line. To add to Rumbo's comment: to compile a *.rc to *.res file you will need a resource compiler. Digital Mars's C/C++ tools [1] include one, but I suspect only for x86. But, if you are on Windows, all of the recent Windows SDKs bundle the resource compiler as well - in both x86 and x64 versions. On my PC I have rc.exe as part of SDK v7.1... c:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\RC.Exe c:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\x64\RC.Exe ..as well as part of SDK v8.1: c:\Program Files (x86)\Windows Kits\8.1\bin\x64\rc.exe c:\Program Files (x86)\Windows Kits\8.1\bin\x86\rc.exe I don't have SDK 10 installed, but that will probably also contain it. You should be able to get the individual SDKs from [2] or as part of a Visual Studio download. [1] http://ftp.digitalmars.com/bup.zip [2] https://developer.microsoft.com/en-us/windows/downloads/sdk-archive
Re: How polymorphism work in D?
On Wednesday, 6 November 2019 at 06:27:32 UTC, OiseuKodeur wrote: On Wednesday, 6 November 2019 at 06:05:25 UTC, rikki cattermole wrote: On 06/11/2019 6:43 PM, OiseuKodeur wrote: I have this [snip] Rikki's answer is the direct answer to your question since you already had the if(..) statements coded in your main function, but your code does not really exploit the main abstraction advantage that polymorphism offers. The typical use of polymorphism in terms of your example would be where you don't want to mess with the interior details of derived classes in your main function - you want to code your logic in your main function just keeping the 'interface' as defined by Foo in your head. Something like this: abstract class Foo { void writeProp(); } class Bar : Foo { float value; this(float t_value) { value = t_value; } override void writeProp() {value.writeln;} } class Baz : Foo { string name; this(string t_name) { name = t_name; } override void writeProp() {name.writeln;} } void main() { Foo foo = new Bar(10); foo.writeProp; foo.writeln; } The idea is that you can separate Baz and Bar "out of sight" (in a library for example) and write your main logic i.t.o. only Foo's. The advantage will become apparent if you want to add another class, say Boo : Foo. In your case you would need to add another else if(..) clause to your main function in addition to adding the class itself. In the above case you only need to add the class - you don't need to touch the main function.
Re: Is this a bug? +goto
On Thursday, 8 November 2018 at 09:34:34 UTC, Michelle Long wrote: What I am talking about is about an obvious error... OK, so here are your code slightly modified: void main(){ int i; W: if(i==0) goto Q; int x; Q: i++; if(i==1) goto W; writeln("a"); } This code does not even skip the 'int x;' declaration and initialization - it happens the 2nd time after the goto to W - but still errors with exactly the same error i.e. 'goto skips declaration of variable x'. so this is _clearly_ a bug in the compiler (right?), even more so than your original case, since the declaration + initialization are not in fact skipped here. The reason for this behavior is what Jonathan and others have tried to explain to you numerous times i.e. that the compiler does not do flow analysis, and hence cannot detect that the above is in fact working code. You seem to be stuck on your premise that the compiler should be able to detect your "trivially obvious case", but would you also expect the compiler to detect the above case? You seem unwilling to accept that it is a reasonable trade-off that the compiler does not detect your "trivially obvious case", since the general case can be arbitrarily complex - and D currently simply does not do flow analysis. Maybe in the future it will do some form of flow analysis (let's hope!), but currently it doesn't. This isn't some 'conspiracy' or 'mindless' defense of the status quo like you seem to claim: What you will find with some of these guys is they start with the assumption that everything D does is correct then they try to disprove anything that goes against it by coming up with reasons that explain why D does it the way it does. It is circular reasoning and invalid. Each step >>> they come up with some new explanation when you pick holes in their previous >>> ones. If the above was really the case there wouldn't be over 4000 bugs open in D at the moment [1], since they would be (according to you) be rationalized as 'features', not 'bugs', right? But above all ... I really think that you need to calm down a notch or 2, you are seeing way too many conspiracies here. Stuff like this... >> Don't let their psychobabble fool you. They are wrong and >> you were right from the start. [snip] Is it logical that the compiler **should** error out in the first case and no in the second? That is what the discussion is ALL about. [snip] THAT IS FACT! It doesn't matter if the examples work above. I have simplified what I have done and in my code I simply add brackets and it works! That is what people should be thinking about... [snip] ... You can assume that I know how scopes work. [snip] You shouldn't assume everyone can't comprehend such trivialities. [snip] What happens when you do that you just create noise that makes it more difficult to have a proper discussion that gets at the whole point of the conversation. You seem to default to assuming that the person you are talking to has no clue about the problem at hand. You really seem just a tad too certain of your facts and that everyone else are just being obstructionists and incapable of seeing your point. In fact you seem to be the one to block out any 'other' factors raised by others (such as flow analysis), and just keep seeing the issue in this simplistic "this is my view and (I quote) 'what the discussion is ALL about'... ". Are you really so convinced that only 'you' are seeing the forest for the trees..? I notice you started off the same way in your 'Dustmite + Visual D' thread in the IDE category, chastising Valdimir who 'dared' to contradict you: As the error message says, the problem occurs because another file is accessing it. No, have you not learned in your life time that just because something or someeone says something doesn't make it true? And then, in your typical self-assured way, corrected Vladimir for his 'foolish idea' that the issue is unlikely to be the junction: Let me enlighten you a little: The reason why this is most likely a junction is: [snip] Wow, to be so certain of yourself must be really nice... but... maybe a bit foolish, since in the end it turned out ... Vladimir was correct. But I guess the words "I was wrong" are not really in your vocabulary, is it? Maybe you need to take a long calm look at yourself in the mirror... no-one here is out to "get you", in fact no-one here thinks that the "D-way" is perfect! In fact, most of the old-timers here are probably, more than most, aware of the warts in D. Stick around on these forums for a few years and you will see epic debates between the core developers on why feature 'X' is broken, and what should be done to fix it! But most of all... virtually every person that responded on this thread tried to help you, or at least debate with you on the why's and the how's... but you seem to take disagreements as persona
Re: Data structures and algorithms in D?
On Sunday, 7 October 2018 at 20:27:47 UTC, eastanon wrote: Are there reading resources on Data structures and Algorithms in D? There are several such books in the C/C++ and Java world and many senior/experienced D users might have come across them in C. But for people who join D after reading Ali's book, a data structures and algorithms book in D would be a great next step. i.e. a book that uses D's idioms and best practices. Any such material in development or recommended blog posts? AFAIK there is no specific book that focuses and delves into Data structures and Algorithms specifically, however there are some books (besides Ali's) that touches on it - at least in a limited sense specific to the topics in each book. For example, Adam D. Ruppe's 'D Cookbook' has a chapter on Ranges, which also covers using ranges when implementing/using algorithms. Likewise Michael Parker's 'Learning D' book has 2 chapters that touches on Ranges and Algorithms: - Chapter 6: Understanding Ranges - Chapter 7: Composing Functional Pipelines with Algorithms and Ranges I'm not sure about Andrei's TDPL book - I read it so long ago I cannot remember. (And I don't have my copy with me so I cannot check). And Kai Nacke's 'D Web Development' book does not really cover these topics either. Of the above-mentioned 2 books (that do cover it), I think Michael's book is the better resource at the moment (that I am aware of anyway). But I'm not sure if I will claim that it covers these topics better than Ali's book at the moment - so maybe it is not going to be good enough for you either. Ali's book anyway seems to be regularly updated (since he self-publishes it) to be up-to-date with the latest in the D language/ecosystem, so I think we will see any new info on this in Ali's book before any other book manages to bring out a new edition (the other books just regularly published - so are in effect really snapshots of the language at the time of publication). Of course, this is besides the problem that containers are (still!) somewhat lacking in D compared to other languages - you just need to look at [1] to see that. [1] https://dlang.org/phobos/std_container.html
Link to https://run.dlang.io/ ??
It would be nice if there was a link to https://run.dlang.io/ on the dlang website - preferably under Resources drop-down menu or similar. Or is there somewhere and I am just missing it? I have bookmarked it for myself, but it would be better for newbies if it was also easily accessible from the website.
Re: Error in template instantiation from D-Cookbook example
On Friday, 9 February 2018 at 21:39:22 UTC, Adam D. Ruppe wrote: On Friday, 9 February 2018 at 21:31:29 UTC, ShadoLight wrote: [1] https://run.dlang.io/is/dyElXg There's missing quotes in there: Line 14: code ~= "push(call!"~piece~"(pop(), pop()));\n"; Should be: code ~= "push(call!\""~piece~"\"(pop(), pop()));\n"; [snip] On Friday, 9 February 2018 at 21:58:51 UTC, Meta wrote: On Friday, 9 February 2018 at 21:31:29 UTC, ShadoLight wrote: [snip] The problem becomes apparent once you uncomment one of these and paste the offending string ("5 5 + 3 - 2 * 1 + 3 /") in. [snip] push(call!+(pop(), pop())); [snip] So it takes a string as its sole template argument. The problem is that the code in convertToD forgot to add the quotes around the operators that are supposed to be passed as strings to call. [snip] Indeed, that makes sense! Thanks to you both! Adam, you are right - it was indeed incorrectly mangled... it is shown as... code ~= "push(call!'"~piece~"'(pop(), pop()));\n"; So the escaped quotes \" were mangled as '. I simply removed them since I assumed they were typos in the doc, similar to the other ones I had fixed. My bad. Man, I cannot believe how quickly you guys answered. Thanks again!
Error in template instantiation from D-Cookbook example
Hi, Trying to improve my CT-fu, I looked at a DSL example (chapter 9) in Adam's D-Cookbook. Although I am sure Adam's original examples would have worked, there were some errors in the example code in the book. The example also contains some code to allow you to test the functions at RT, which had an error i.e. I had to change this... writeln(parse(code)); // to aid with debugging writeln(convertToD(parse(code))); // debugging aid ..to.. writeln(parse(code)[]); // to aid with debugging writeln(convertToD(parse(code))[]); // debugging aid ..to match the actual function arguments. So that worked fine. However I could not get the CT version to work with the current version of DMD i.e. this [1]... [1] https://run.dlang.io/is/dyElXg ...fails with: onlineapp.d-mixin-36(38): Error: template argument expected following ! onlineapp.d(48): Error: template instance onlineapp.runDslCode!"5 5 + 3 - 2 * 1 + 3 /" error instantiating. I find the error message a bit lacking as to the real cause - I really cannot see where the "template argument expected following !" error is. It all looks correct to me. In addition the RT version is working correctly (after fixing the above bug), so that is not helping in identifying the error - particularly since it is failing in the only CT specific function not used/called at RT. So I am not sure how to debug this. Can somebody please put me out of my misery here? Thx!