gtkDcoding Blog Post #0025 - LinkButtons
Good morning! A new post is up on the gtkDcoding blog. It's all about the LinkButton and you can find it here: http://gtkdcoding.com/2019/04/09/0025-creating-and-using-a-linkButton.html
Re: D threading and shared variables
On Sunday, 7 April 2019 at 22:18:56 UTC, Johan Engelen wrote: On Sunday, 7 April 2019 at 14:08:07 UTC, Archie Allison wrote: This generally works OK when tied to a Console but when link options are changed to be SUBSYSTEM:WINDOWS and ENTRY:mainCRTStartup it rarely does. Manually setting the entry point sounds problematic if no other precautions are taken. Are you sure that druntime is initialized? See [1]. - Johan [1] https://wiki.dlang.org/D_for_Win32 I changed the main code as described in the article but the effect seems to be the same as just using the link options. Is there anything obviously wrong with the variable declarations in the code sample? It looks like having a console output window in addition to just the GUI is having some sort of effect on threading, sharing or timing.
Re: Templates - What's Up with the template keyword?
On Monday, 8 April 2019 at 14:56:46 UTC, Mike Parker wrote: In the subsequent sections, I show both long and short (eponymous) forms of enum and function templates. In your book, Mike, you stated: Remember, a template is only instantiated once for each set of arguments and the same instantiation can be repeated in multiple modules throughout a program. If each instantiation were scoped locally, the template would no longer work as expected. That leads me to speculate that it should be possible to use a class template as a sort of singleton. But, because a class template (from what I understand currently) needs to be instantiated using 'new,' I'm thinking maybe it isn't possible. Can you (or someone else) clear this up for me, please? What I have in mind is a template wrapped around a GTK AccelGroup that could then be instantiated in the MainWindow as well as inside any MenuItem needing a keyboard shortcut assignment.
Re: Templates - What's Up with the template keyword?
On Tuesday, 9 April 2019 at 10:53:49 UTC, Ron Tarrant wrote: On Monday, 8 April 2019 at 14:56:46 UTC, Mike Parker wrote: In the subsequent sections, I show both long and short (eponymous) forms of enum and function templates. In your book, Mike, you stated: Remember, a template is only instantiated once for each set of arguments and the same instantiation can be repeated in multiple modules throughout a program. If each instantiation were scoped locally, the template would no longer work as expected. That leads me to speculate that it should be possible to use a class template as a sort of singleton. But, because a class template (from what I understand currently) needs to be instantiated using 'new,' I'm thinking maybe it isn't possible. Can you (or someone else) clear this up for me, please? Instantiating a class template is not like instantiating a single instance of an object. What it does is create an implementation of the class, not an instance. So given this: class Foo(T) { T item; } Then this instantiation (which, byt the way, does not need new -- an alias will do the trick): alias IntFoo = Foo!int; Essentially does this: class FooWithInt { int item; } Of course, the symbol will be different than 'FooWithInt', but the point is for every T there has to be a uniquely named implementation of Foo. What I have in mind is a template wrapped around a GTK AccelGroup that could then be instantiated in the MainWindow as well as inside any MenuItem needing a keyboard shortcut assignment. Off the top of my head, to get a Singleton template, you could implement all of your singleton plumbing (thread safety if you need it, etc) in the template and add a `static _instance` member just as you would for any non-templated singleton: class Singleton(T) { private static Singleton!T _instance; static Singleton!T instance() { if(_instance is null) { _instance = new Singleton!T; } ... } private T _thing; ... } And you can then instantiate directly or, more conveniently, use an alias: alias Accelerators = Singleton!AccelGroup; Then: Accelerators.instance.doSomething();
Re: Templates - What's Up with the template keyword?
On Monday, 8 April 2019 at 12:23:28 UTC, Ron Tarrant wrote: I'm digging into templates in an attempt to understand the signals-n-slots replacement for the observer pattern, but I've got a question I can't seem to find an answer for and an example for which I'm unable to solve the error. First, the question... Your confusion arises in your understanding of meta programming and templates. Templates are compile time expressions that use parameters. They are exactly analogous to parameters in typical programming but allow one to pass around CT information that doesn't exist at run time. It is not the statement itself that is a template but the fact that it depends on a "template", which is a sort of abstract variable. class C(T) template C(T) struct(T) interface(T) void foo(T)() etc... are all things that depend on a template parameter T. One can say that they are all "templated" or are "templates". One can also say they are parameterized(meaning they take a parameter, but the parameters are CT "objects". Essentially template is the most general and the rest are just syntactic sugar. e.g., template CC(T) { class C { T t; } } template CC is a "template"(just like a cookie cutter but that can configure itself depending on what T is, as this example shows that we can create a class with different type of t. D has all kinda of stuff like this that help reduce the bloat of templates. Sometimes you must use one method over another for certain effects but usually you can pick and choose. The idea is not to think of meta programming as something different than normal programming. It is still programming and there is enough of an overlap that it benefits one to realize they are the same thing but are at different levels in the type system. Meta programming works on the type hierarchy while "runtime programming" works in the type hierarchy. Meta programming is a super set of runtime programming. The way I think of meta programming is that of coding runtime code. Run time code codes binary code. If I create a statement like writeln("test"); I know that the code gets translated in to a call instruction, pointers are used, "test" exists in some location in memory, etc... it all is machine code though when I compile. When I do something like this foo!int(); I know that the first part of foo!int is "meta code" and it first gets translated in to runtime code and then that code gets translated in to machine code. For example void foo(T)(T s) { writeln(s); } in this case, depending on what T is at compile time(which I get to decide in some way and so I know exactly what it is at compile time, in theory), foo takes on different versions. if I call foo(3) then it is writeln(3) and T is an int(by deduction in the compiler) and the compiler can even optimize out certain things here because it also knows that 3 is known.(this is CTFE) There is nothing to optimize in that example though. if I call foo(readln()) then the the compiler cannot optimize out but this code get translated in to writeln(readlin()) but T is a string(since readln returns a string and the compiler can deduce it). But in general foo acts as all these possibilities(and all the possibilities are known by the compiler because they have to be known to compile and use). So, what does templates do? They combine very similar code in to meta blocks that can then be easily used. They allow constructing very complex meta code such as void foo(T)(T s) { static if (is(T == string)) writeln(s); } and now foo is much more complicated because it has two completely different behaviors depending on what T is. You can't get that with run time code without a lot of work and it will never be efficient. But here the compiler will eventually know what T is and it can then choose the correct path at compile time. The if will disappear and so no extra overhead exists at runtime. So, templates are very powerful things(the above doesn't even dent their power) The idea to bear in mind is that anything in D is a template if it takes a template parameter. Think of a template as a drawing template used to sketch something. It isn't the final result but it shapes the final result. It is more like a blueprint or a program in and of itself. I think the hard part for many is that they can't balance the meta programming part with the run time part. This is very easy though if one always just keeps track of which side one is programming in and not to mix them up(mentally). The meta programming part will always be obvious, it will depend on template parameters and use meta programming constructs. There are sometimes overlap between the two levels but it because natural once one gets enough of an understanding. The hardest part about D is that it has so much meta programming stuff and there are sometimes bugs and special cases to do things, but the grammatical de
Re: const of AliasSeq is silently ignored
On Monday, 8 April 2019 at 19:56:50 UTC, Yuxuan Shui wrote: In this example: const(AliasSeq!(int, int)) a; pragma(msg, typeof(a)); // (int, int) This kind of make sense, since AliasSeq is not a "single" type. But silently dropping const seems bad, the compiler should probably report an error/warning in this case? kinda makes sense and making sense are two different things. It has to make sense to the compiler. While I see that you want to distribute const over the list, D is not designed to do this with anything that I know of. It could, without issue, but one must makes sure it does not contradict any other uses. If it doesn't then it could be a bonus feature. Normally though one expects const to work on it's argument and so this also suggests having a const AliasSeq. Since we can't have a const AliasSeq there may be no issue redefining it to me what you want. I agree that silently dropping things are bad. D does this sometimes and it can be a real pain.
Re: Overloads not returning appropriate info. [Field reflunkory]
On Monday, 8 April 2019 at 21:52:59 UTC, Adam D. Ruppe wrote: On Saturday, 6 April 2019 at 12:20:28 UTC, Alex wrote: Error: variable `std.traits.ParameterDefaults!(foo).Get!1u.Get` only parameters or stack based variables can be `inout` so i think that is a bug in the phobos library see: https://forum.dlang.org/thread/qbqvkcoexxtlvlxob...@forum.dlang.org I appreciate you looking in to it instead of writing it off. It basically proves my point that there are issues with D. These issues tend too be subtle and creep in to code and then that causes problems. I have been thrown off several times and when things don't work out I assume it is my code and when it's not I've already trashed my code trying to figure out what was wrong with it. These are the real problems with D and they come from two things: Not having a uniform and direct interface for reflection. Not having proper unit testing done for traits. D is so heavy in meta programming that maybe it is time for a proper solution?
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 14:42:38 UTC, Alex wrote: It basically proves my point that there are issues with D. The language is fine in this case, it is a bug in the library. Though, I don't think the library can be fixed because the language doesn't have facilities to express these things through libraries but I also don't see the point in having a library at all. You incur compile time and run time costs for stuff you probably don't need and introduce another layer of bugs. Some of the lower level features are a little weird to see*, but they are easy to use once you get to know them. * for example static if(is(typeof(overload) Params == __parameters)) to get the function parameter list (as the Params variable there). It is a little weird looking, but it isn't really hard to use.
Re: const of AliasSeq is silently ignored
On Monday, 8 April 2019 at 19:56:50 UTC, Yuxuan Shui wrote: In this example: const(AliasSeq!(int, int)) a; pragma(msg, typeof(a)); // (int, int) This kind of make sense, since AliasSeq is not a "single" type. But silently dropping const seems bad, the compiler should probably report an error/warning in this case? It works if you use the "storage class" syntax for const: const AliasSeq!(int, int) a; pragma(msg, typeof(a)); // (const(int), const(int))
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 14:59:03 UTC, Adam D. Ruppe wrote: On Tuesday, 9 April 2019 at 14:42:38 UTC, Alex wrote: It basically proves my point that there are issues with D. The language is fine in this case, it is a bug in the library. I didn't say the language. The point with the language is that it could have built in semantics to do reflection in a inform way(__traits is somewhat uniform but messy and then one has std.traits which then makes it not uniform). Though, I don't think the library can be fixed because the language doesn't have facilities to express these things through libraries but I also don't see the point in having a library at all. You incur compile time and run time costs for stuff you probably don't need and introduce another layer of bugs. There is no runtime costs. The library may not be efficient but it is a better design. It abstracts most of the crap away and provides a very natural and uniform interface in to reflection. Ultimately the compiler itself should provide this information directly. It has all the information when it compiles and it can lazily instantiate whatever information it has to calculate when it is requested. It could be very efficient, it is just doing what __traits does but more naturally. Reflection should be a first class semantic in D given D's heavy meta programming capabilities. Some of the lower level features are a little weird to see*, but they are easy to use once you get to know them. * for example static if(is(typeof(overload) Params == __parameters)) to get the function parameter list (as the Params variable there). It is a little weird looking, but it isn't really hard to use. The problem is that there is a semantic that supposedly exists to dot he same but fails. So it is not about weirdness but about non-uniformity. Why does it have to be that way? There is no reason, it is also a hack in the compiler. WHy not just wrap that code with something sane like Type.Reflect!Parameters ? This is exactly what my library does and it is a more sane looking solution. It's that simple. You can't disagree, you know it looks better(we could argue about the precise syntax but it is much better and more informative than what you posted). Also, your snippet is meant to be used, later on, such as in a for each loop, when we could do static foreach(p; Type.Reflect!Parameters) vs static if(is(typeof(overload) Params == __parameters)) static foreach(p; Params) It's 50% savings in both line space and character space, it's much faster to understand, it is uniform and natural while the second case is ugly, confusing, and bloated. My point is that THERE IS NO NEED for such things. It is ALL about syntax. It's just wrappers. There is no new functionality. I'm just trying to make things "look" better because things that "look" better are easier to comprehend. Look better means that they are more uniform with common practices and experiences and allow for easier navigation in memory space. You may be ok with having to remember special cases here and their... but it is a defect. Suppose you program in 10 languages regularly, those special cases then are an order of magnitude more to remember... suppose you do other things with your life. If you don't and all you do is program D then you don't feel it as bad, if you do lots of other things then these are speed bumps that slows one down for no good reason at all(if you have one, besides, "some one has to code the new syntax and it takes work to make it better" then I'd like to hear it). What I see if you justifying bad syntax just to justify it because it exists. If I'm wrong you just have to give me meaningful reasons why that is not the case. I'm not looking to be confrontational, I'm looking to make things better. If you are right about what you claim then you can back it up, if not you can't except with fallacious arguments. My mind is willing to be changed as long as the change is provably good, else there is no point in going backwards. I think the only argument you have is "It already exists and works and is not too bad"... which may be a good enough argument for you but isn't for me. That type of argument can be used to prevent progress on anything. "The cave is already exists and works to keep us sheltered and is not that bad so we don't need to build a nice house with AC that takes work to do". If all you have ever lived in is a cave then you can't possibly know if the house is better. It has to be built first to compare and contrast. The secret is that there is always something better than something else and it always should be sought after, at least theoretically(sure there is the practical issue of time, I accept that, but I don't accept denial that their isn't something better). Hell, as much time that we have spent arguing over this shit we could have probably created a language feature
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 16:30:53 UTC, Alex wrote: On Tuesday, 9 April 2019 at 14:59:03 UTC, Adam D. Ruppe wrote: [...] I didn't say the language. The point with the language is that it could have built in semantics to do reflection in a inform way(__traits is somewhat uniform but messy and then one has std.traits which then makes it not uniform). [...] Have you considered writing a DIP?
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tue, Apr 09, 2019 at 06:33:21PM +, Seb via Digitalmars-d-learn wrote: > On Tuesday, 9 April 2019 at 16:30:53 UTC, Alex wrote: > > On Tuesday, 9 April 2019 at 14:59:03 UTC, Adam D. Ruppe wrote: > > > [...] > > I didn't say the language. The point with the language is that it > > could have built in semantics to do reflection in a inform > > way(__traits is somewhat uniform but messy and then one has > > std.traits which then makes it not uniform). > > > > [...] > > Have you considered writing a DIP? I think the original intent was that __traits was supposed to be low-level, implementation-specific calls into the compiler, while std.traits is supposed to be the user-friendly syntactic sugar built on top that user code is supposed to use. Unfortunately, it turned out that people prefer using __traits directly instead, and std.traits hasn't quite been keeping up with new __traits (e.g., AFAIK __traits(compiles) does not have a std.traits equivalent), and is also less familiar to many people, so now we have a mishmash of code sometimes using __traits and sometimes std.traits. T -- VI = Visual Irritation
Re: Templates - What's Up with the template keyword?
On Tuesday, 9 April 2019 at 14:25:18 UTC, Mike Parker wrote: Off the top of my head, to get a Singleton template, you could implement all of your singleton plumbing (thread safety if you need it, etc) in the template and add a `static _instance` member just as you would for any non-templated singleton: class Singleton(T) { private static Singleton!T _instance; static Singleton!T instance() { if(_instance is null) { _instance = new Singleton!T; } ... } private T _thing; ... } And you can then instantiate directly or, more conveniently, use an alias: alias Accelerators = Singleton!AccelGroup; Then: Accelerators.instance.doSomething(); So, I guess the short answer is 'no.' A template can't really substitute for a singleton without actually becoming a singleton in and of itself. I'm still struggling to understand templates, but I'll keep at it. Thanks, Mike.
Re: Templates - What's Up with the template keyword?
On Tuesday, 9 April 2019 at 14:41:30 UTC, Alex wrote: Your confusion arises in your understanding of meta programming and templates. Templates are compile time expressions that use parameters. This sounds like another 'no.' :) Thanks for all the info, Alex.
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 18:33:21 UTC, Seb wrote: On Tuesday, 9 April 2019 at 16:30:53 UTC, Alex wrote: On Tuesday, 9 April 2019 at 14:59:03 UTC, Adam D. Ruppe wrote: [...] I didn't say the language. The point with the language is that it could have built in semantics to do reflection in a inform way(__traits is somewhat uniform but messy and then one has std.traits which then makes it not uniform). [...] Have you considered writing a DIP? No, because I expect it won't even be considered. The typical responses I have seen to this sort of thing is that "we already have it". Hence why I decided to write my own lib, and then had a few issues. Andre did look in to some of the ideas and said he would pass it off to some GSOC students to look in to making it better, so maybe something will come out of that. I believe that basically the compiler simply needs to present a better interface in to reflection. This should have been done from the get go but I guess __traits has been patched together over time as as things were needed. Essentially the compiler would need to do what I have done and wrap __traits and std.traits in to a more uniform interface. It would add an extra layer of indirection though since the wrapper needs then to stay consistent with any traits changes. My library works well but is incomplete and has some bugs to due bugs in traits. It is, though, rather slow and I haven't worked on fixing it. (actually it doesn't seem to add too much overhead after the first call but I imagine that is due to the template being instantiated already in the module, might multiply for each new module it is used in) What I'm thinking is that maybe it is better to have some range like semantics used for reflection. I have thought about it much but I got the idea earlier. Type.Reflect.Accessor.Accessor.Selector.Selector.Accessor... The idea is that one can access stuff from the type and then use certain keywords to select and filter and then access more. I say it is range like but I'm not sure if ranges would work or not or if it would just be dispatching. E.g., MyClass.Reflect.TemplateParameters.Select!int.Names Would get the template parameters of MyClass, then select only those with int and then get the names of those parameters. (this could work in general for runtime too) MyClass.SomeArray.Select("x.value == 4").name; which is why I say it is sorta like ranges(which I'm thinking more of piping). I just haven't thought about it much and there doesn't seem to be much interest in going this route... I think it would be a great addition to D but others seem to not care or are more interested in arguing to relatively insignificant issues.
Re: Templates - What's Up with the template keyword?
On 4/9/19 4:31 PM, Ron Tarrant wrote: I'm still struggling to understand templates, but I'll keep at it. When I first saw C++ templates, I thought "what the hell is this black magic", and had no idea how they worked. In fact, this was back before STL, and I recall it was a set of templates called "Rogue Wave". None of us who were working on the project at the time understood them, so we ripped them all out. The thing that made it click for me is that a template is very akin to a macro substitution -- where you just copy and paste the given parameter wherever its substitute is found. For example: struct S(T) { T member; } S!int => put int wherever you see T. So it's like you typed: struct S { int member; } and that's what the compiler sees. All optimization, layout, etc. works exactly like you typed that directly. But instead of creating one type for every member type you need, you just write it once and "instantiate" the template giving the type you want. I will say, it's not EXACTLY the same as macro substitution -- there are rules. But it's a good way to think about it. I actually am going to go over this kind of thinking a bit in my talk this year at dconf. -Steve
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 18:56:58 UTC, H. S. Teoh wrote: On Tue, Apr 09, 2019 at 06:33:21PM +, Seb via Digitalmars-d-learn wrote: On Tuesday, 9 April 2019 at 16:30:53 UTC, Alex wrote: > On Tuesday, 9 April 2019 at 14:59:03 UTC, Adam D. Ruppe > wrote: > > [...] > I didn't say the language. The point with the language is > that it could have built in semantics to do reflection in a > inform way(__traits is somewhat uniform but messy and then > one has std.traits which then makes it not uniform). > > [...] Have you considered writing a DIP? I think the original intent was that __traits was supposed to be low-level, implementation-specific calls into the compiler, while std.traits is supposed to be the user-friendly syntactic sugar built on top that user code is supposed to use. Unfortunately, it turned out that people prefer using __traits directly instead, and std.traits hasn't quite been keeping up with new __traits (e.g., AFAIK __traits(compiles) does not have a std.traits equivalent), and is also less familiar to many people, so now we have a mishmash of code sometimes using __traits and sometimes std.traits. That may be the case but I recently saw some one here say "All the roads to hell are paved with good intentions", which isn't hyperbole. The better the initial plan the better things will turn out. Planning is the key to success, without it there is only luck. My point has been and is that there is a better way that is more natural. I make no claims about anything else. It may be a cop out to say something that is a tautology but I make the claim as an emphasis that I believe that it is more true in this case than others. i.e., D's traits are PITA. Ok, they are not as bad as some things but I know they can be better since I have used other languages that have far more logical reflection(such as C#) than D. Because D has such an extensive meta programming language(the best I've seen for procedural) it needs a well thought out and natural reflection scheme. traits works but the more I use it the more I believe it could have been done better. It's one thing to use it here and there, but when you use it everywhere the issues multiply. I think the library I through together at least demonstrates a much more natural way(and it was just a first attempt without any planning). I imagine something much better could be created with some proper planning and teamwork. My impression though is few people here actually care about such things.
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tue, Apr 09, 2019 at 08:49:17PM +, Alex via Digitalmars-d-learn wrote: > On Tuesday, 9 April 2019 at 18:56:58 UTC, H. S. Teoh wrote: [...] > My point has been and is that there is a better way that is more > natural. I make no claims about anything else. It may be a cop out to > say something that is a tautology but I make the claim as an emphasis > that I believe that it is more true in this case than others. i.e., > D's traits are PITA. Ok, they are not as bad as some things but I know > they can be better since I have used other languages that have far > more logical reflection(such as C#) than D. As I said, __traits was never designed to be user-friendly, or even "logical". It was supposed to be a quick-and-easy way to tap into compiler internals, and std.traits was supposed to be the proper API to introspection. But std.traits, as it stands, is far, far from what it ought to be, and so we have today's sorry situation. (And on a side note: don't even get me started on is(...) expressions.) Anyway, since you seem to be passionate about this, this could be your chance of making std.traits what it ought to have been all along, or making a sensible reflection library that can for all practical purposes replace std.traits. I, for one thing, would appreciate a nicer API to introspection than what we currently have. One of the main things that drew me to D was its metaprogramming capabilities, and while overall it has been a positive experience, there *are* flies in the ointment like __traits, is(...) expressions, etc.. If you or somebody else could come up with a saner way to do introspection in D, it'd be very much appreciated. T -- Life would be easier if I had the source code. -- YHL
Re: Templates - What's Up with the template keyword?
On Tue, Apr 09, 2019 at 04:48:45PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: > On 4/9/19 4:31 PM, Ron Tarrant wrote: > > > I'm still struggling to understand templates, but I'll keep at it. [...] > The thing that made it click for me is that a template is very akin to > a macro substitution -- where you just copy and paste the given > parameter wherever its substitute is found. [...] Yes, templates are, functionally speaking, macros with type safety, and in D's case syntactic sanity, and none of the disadvantages of an actual macro system. T -- Heads I win, tails you lose.
Re: Templates - What's Up with the template keyword?
On 04/08/2019 05:23 AM, Ron Tarrant wrote: > But in "Programming in D," (self, 2009-2018) by Ali Çehreli, there's no > mention of the 'template' keyword in any of his examples. 'template' keyword is introduced here: http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.template I found that page by clicking on one of the two 'template' entries under T in the book's index: http://ddili.org/ders/d.en/ix.html Ali
Re: Templates - What's Up with the template keyword?
On 04/08/2019 05:59 AM, Ron Tarrant wrote: On Monday, 8 April 2019 at 12:40:10 UTC, Adam D. Ruppe wrote: You don't need template keyword for the majority of cases because the compiler lets you do shortcuts. Thanks, Adam. Good to know. (maybe I am looking at the wrong part of the book, it is hard to find the right section/page number online). My bad. The edition I'm working from was released 2018-10-17 and can be found here: http://ddili.org/ders/d.en/Programming_in_D.pdf The page number in online PDF viewer is 421 and the example is about 1/3 of the way down the page. That template specialization works along with the general definition of the same template. So, you must have the following function template as well: T getResponse(T)(string question) { writef("%s (%s): ", question, T.stringof); T response; readf(" %s", &response); return response; } As Steve said, when you replace all Ts in there e.g. with int, you get what the compiler would generate for T being int. However, the readf above cannot work with e.g. Point!double because readf does not know what Point!double is. For that reason, we may use a specialization for Point!T: Point!T getResponse(T : Point!T)(string question) { writefln("%s (Point!%s)", question, T.stringof); auto x = getResponse!T(" x"); auto y = getResponse!T(" y"); return(Point!T(x, y)); } // getResponse() Point!T (It may be made to work with Adam's (T : Point!R, R) syntax but I failed just now.) Now you have a specialization that works with any Point!T. T can be double, int, etc. However, you must call getResponse with that special Point. I'm using an alias for code reduction: alias MapLocation = Point!double; auto wayPoint1 = getResponse!MapLocation("Where is the first map location?"); auto wayPoint2 = getResponse!MapLocation("Where is the second map location?"); Your code did not work because Point is not a type but a type template. (On the other hand, Point!double is a type). The whole program: import std.stdio; import std.math; import std.string; struct Point(T) { T x; T y; T distanceTo(Point that) const { immutable real xDistance = x - that.x; immutable real yDistance = y - that.y; immutable distance = sqrt((xDistance * xDistance) + (yDistance * yDistance)); return(cast(T)distance); } // distanceTo() } // struct Point T getResponse(T)(string question) { writef("%s (%s): ", question, T.stringof); T response; readf(" %s", &response); return response; } Point!T getResponse(T : Point!T)(string question) { writefln("%s (Point!%s)", question, T.stringof); auto x = getResponse!T(" x"); auto y = getResponse!T(" y"); return(Point!T(x, y)); } // getResponse() Point!T void main() { alias MapLocation = Point!double; auto wayPoint1 = getResponse!MapLocation("Where is the first map location?"); auto wayPoint2 = getResponse!MapLocation("Where is the second map location?"); writeln("Distance: ", wayPoint1.distanceTo(wayPoint2)); } // main() Ali
Re: Templates - What's Up with the template keyword?
On Wednesday, 10 April 2019 at 00:42:11 UTC, Ali Çehreli wrote: (It may be made to work with Adam's (T : Point!R, R) syntax but I failed just now.) You know, I didn't think T : Point!T would work, but it does. Huh. Anyway, the , R one works similarly, observe: --- T getResponse(T : Point!R, R)(string question) { writef("%s (%s): ", question, T.stringof); R response; readf(" %s", &response); return T(response); } --- In this case, when you pass it a Point!double, T is still the full type, Point!double (so the return value there needs to be constructed), but R is now just the `double` part, so we can pass that independently to readf. This pattern is also useful for capturing static arrays: void processStaticArray(A : T[N], T, size_t N)(ref A) { writeln(T.stringof, " ", N); } void main() { int[5] arr; processStaticArray(arr); } There, A is our static array type, but then we deconstruct its pieces to get the size and inner type too. This lets us pass any static array in without losing the compile-time length. (though usually I'd just slice it and call it T[]!) These patterns are also used by the `is` expression, and you can rename the whole thing there when used inside `static if`. (I know most people think this is crazy black magic, but it actually isn't that crazy once you know the pattern - write the symbol with placeholders, add a comma, define the placeholders. Then the other forms like is(T == X) and is(T : X) and even is(T N == X) are just optional additions to this - == means is equal to, : means can convert to, and the N in the last one renames the value extracted to something else, most valuable in is(typeof(func) Params == __parameters). So yeah, there is a bit to it, but it is just a pattern, condition, optional placeholders, optional rename.)
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 20:45:18 UTC, Alex wrote: On Tuesday, 9 April 2019 at 18:33:21 UTC, Seb wrote: Have you considered writing a DIP? No, because I expect it won't even be considered. You won't pass review if you don't show knowledge of the existing language, but there's a lot of people who are interested in a few changes. A few years ago, there was a proposal for a magical `meta` namespace that would call into the compiler for syntax sugar on CT reflection. The old idea was to replace `__traits(X, args)` with `meta.X(args)` - pure syntax change - but you could perhaps revive and expand that as the entry point to your new idea and get some people on board. I'm skeptical of any reflection library, but compiler changes might be able to change that. The status quo for D's reflection libraries are: 1) weird bugs and/or omissions since the language does not let you express all the function parameter details as return values or local variables. 2) slow compile times (you said your thing was 10 seconds! that's utterly unacceptable) 3) not actually significantly easier to use than language built-ins (if they are actually easier to use at all!) So any library without compiler changes is, as of today, I believe *impossible* to get right, and getting as close as you can is horribly slow. So, your DIP would necessarily include language+compiler changes. And the compiler is *already* (almost) fully capable, so changing that needs to show that the change is worth it. Maybe you can do that, even little cosmetic things can indeed be a win, but to write a convincing case here, you'll need to compare and contrast various cases.
Re: Overloads not returning appropriate info. [Field reflunkory]
On Tuesday, 9 April 2019 at 21:00:55 UTC, H. S. Teoh wrote: (And on a side note: don't even get me started on is(...) expressions.) is expressions rock. And I betcha if we did do libraries for them, it would eventually go full circle, with someone doing a pattern-matching DSL that reinvents the original syntax, just much slower to compile :P
Re: Overloads not returning appropriate info. [Field reflunkory]
Another couple ideas you might get some traction on are making typeid() values be convertible back into typeof types iff CTFE. That would let you use types as OOP class values in intermediate structures while still turning them back into template args later. Not sure just how realistic that is, but might be fun to explore. Related would be to use RTInfo in druntime to extend the typeid info to runtime data, based on a -version switch. This should be possible in today's language fairly easily, though it would not be customizable by the end user, you could perhaps just make it include it all.