Re: Bug in D!!!
On Wednesday, 30 August 2017 at 20:47:12 UTC, EntangledQuanta wrote: interface I { void Go(T)(S!T s); static final I New() { return new C(); } } abstract class A : I { } class C : A { void Go(T)(S!T s) { } } This is a blocker for me! Can someone open a ticket? Judging by the length of the thread that I did not read, the real problem was not spotted, otherwise, it would be shorter. The problem is called "virtual method in the interface" anti-pattern. Just never do that, and life will be easier. In this case, I recommend to move Go to A and make it just dispatcher for specialized private non-templated virtual functions. You don't need all this mess with string templates for it.
Re: Bug in D!!!
On Monday, 4 September 2017 at 03:08:50 UTC, EntangledQuanta wrote: On Monday, 4 September 2017 at 01:50:48 UTC, Moritz Maxeiner wrote: On Sunday, 3 September 2017 at 23:25:47 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 11:48:38 UTC, Moritz Maxeiner wrote: On Sunday, 3 September 2017 at 04:18:03 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 02:39:19 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: [...] The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). Why? Don't you realize that the contexts matters and [...] Because instead of seeing the keyword and knowing its one meaning you also have to consider the context it appears in. That is intrinsically more work (though the difference may be very small) and thus harder. ... Yes, In an absolute sense, it will take more time to have to parse the context. But that sounds like a case of "pre-optimization". I don't agree, because once something is in the language syntax, removing it is a long deprecation process (years), so these things have to be considered well beforehand. That's true. But I don't see how it matters to much in the current argument. Remember, I'm not advocating using 'in' ;) [...] It matters, because that makes it not be _early_ optimization. If we are worried about saving time then what about the tooling? compiler speed? IDE startup time? etc? All these take time too and optimizing one single aspect, as you know, won't necessarily save much time. Their speed generally does not affect the time one has to spend to understand a piece of code. Yes, but you are picking and choosing. [...] I'm not (in this case), as the picking is implied by discussing PL syntax. So, in this case I have to go with the practical of saying that it may be theoretically slower, but it is such an insignificant cost that it is an over optimization. I think you would agree, at least in this case. Which is why I stated I'm opposing overloading `in` here as a matter of principle, because even small costs sum up in the long run if we get into the habit of just overloading. I know, You just haven't convinced me enough to change my opinion that it really matters at the end of the day. It's going to be hard to convince me since I really don't feel as strongly as you do about it. That might seem like a contradiction, but I'm not trying to convince you of anything. Again, the exact syntax is not import to me. If you really think it matters that much to you and it does(you are not tricking yourself), then use a different keyword. My proposal remains to not use a keyword and just upgrade existing template specialization. [...] You just really haven't stated that principle in any clear way for me to understand what you mean until now. i.e., Stating something like "... of a matter of principle" without stating which principle is ambiguous. Because some principles are not real. Some base their principles on fictitious things, some on abstract ideals, etc. Basing something on a principle that is firmly established is meaningful. I've stated the principle several times in varied forms of "syntax changes need to be worth the cost". I have a logical argument against your absolute restriction though... in that it causes one to have to use more symbols. I would imagine you are against stuff like using "in1", "in2", etc because they visibly are to close to each other. It's not an absolute restriction, it's an absolute position from which I argue against including such overloading on principle. If it can be overcome by demonstrating that it can't sensibly be done without more overloading and that it adds enough value to be worth the increases overloading, I'd be fine with inclusion. [...] To simplify it down: Do you have the sample problems with all the ambiguities that already exist in almost all programming languages that everyone is ok with on a practical level on a daily basis? Again, you seem to mix ambiguity and context sensitivity. W.r.t. the latter: I have a problem with those occurences where I don't think the costs I associate with it are outweighed by its benefits (e.g. with the `in` keyword overloaded meaning for AA's). Not mixing, I exclude real ambiguities because have no real meaning. I thought I mentioned something about that way back when, but who knows... Although, I'd be curious if any programming languages existed who's grammar was ambiguous and actually could be realized? Sure, see the dangling else problem I mentioned. It's just that people basically all agree on one of the choices and all stick with it (despite the grammar being formally ambiguou
Re: Bug in D!!!
On Monday, 4 September 2017 at 01:50:48 UTC, Moritz Maxeiner wrote: On Sunday, 3 September 2017 at 23:25:47 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 11:48:38 UTC, Moritz Maxeiner wrote: On Sunday, 3 September 2017 at 04:18:03 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 02:39:19 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: [...] The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). Why? Don't you realize that the contexts matters and [...] Because instead of seeing the keyword and knowing its one meaning you also have to consider the context it appears in. That is intrinsically more work (though the difference may be very small) and thus harder. ... Yes, In an absolute sense, it will take more time to have to parse the context. But that sounds like a case of "pre-optimization". I don't agree, because once something is in the language syntax, removing it is a long deprecation process (years), so these things have to be considered well beforehand. That's true. But I don't see how it matters to much in the current argument. Remember, I'm not advocating using 'in' ;) I'm only saying it doesn't matter in a theoretical sense. If humans were as logical as they should be, it would matter less. For example, a computer has no issue with using `in`, and it doesn't really take any more processing(maybe a cycle, but the context makes it clear). But, of course, we are not computers. So, in a practical sense, yes, the line has to be draw somewhere, even if, IMO, it is not the best place. You agree with this because you say it's ok for parenthesis but not in. You didn't seem to answer anything about my statements and question about images though. But, I'm ok with people drawing lines in the sand, that really isn't what I'm arguing. We have to draw lines. My point is, we should know we are drawing lines. You seem to know this on some significant level, but I don't think most people do. So, what would happen, if we argued for the next 10 years, we would just come to some refinement of our current opinions and experiences about the idea. That's a good thing in a sense, but I don't have 10 years to waste on such a trivial concept that really doesn't matter much ;) (again, remember, I'm not advocating in, I'm advocating anything, but against doing nothing.) If we are worried about saving time then what about the tooling? compiler speed? IDE startup time? etc? All these take time too and optimizing one single aspect, as you know, won't necessarily save much time. Their speed generally does not affect the time one has to spend to understand a piece of code. Yes, but you are picking and choosing. To understand code, you have to write code, to write code you need a compiler, ide, etc. You need a book, the internet, or other resources to learn things too. It's a much much bigger can of worms than you realize or want to get in to. Everything is interdependent. It's nice to make believe that we can separate everything in to nice little quanta, but we can't, and when we ultimately try we get results that make no sense. But, of course, it's about the best we can do with where humans are at in their evolution currently. The ramifications of one minor change can change everything... See the butterfly effect. Life is fractal-life, IMO(I can't prove it but the evidence is staggering). I mean, when you say "read code faster" I assume you mean the moment you start to read a piece of code with your eyes to the end of the code... But do you realize that, in some sense, that is meaningless? What about the time it takes to turn on your computer? Why are you not including that? Or the time to scroll your mouse? These things matter because surely you are trying to save time in the "absolute" sense? e.g., so you have more time to spend with your family at the end of the day? Or spend more time hitting a little white ball in a hole? or whatever? If all you did was read code and had no other factors involved in the absolute time, then you would be 100% correct. But all those other factors do add up too. Of course, the more code you read the more important it becomes and the less the other factors become, but then why are you reading so much code if you think it's a waste of time? So you can save some more time to read more code? If your goal is to truly read as much code as you can in your life span, then I think your analysis is 99.999...% correct. If you only code as a means to an end for other things, then I think your answer is about 10-40% correct(with a high degree of error and dependent on context). For me, and the way I "value"/"judge
Re: Bug in D!!!
On Sunday, 3 September 2017 at 23:25:47 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 11:48:38 UTC, Moritz Maxeiner wrote: On Sunday, 3 September 2017 at 04:18:03 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 02:39:19 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: [...] The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). Why? Don't you realize that the contexts matters and [...] Because instead of seeing the keyword and knowing its one meaning you also have to consider the context it appears in. That is intrinsically more work (though the difference may be very small) and thus harder. ... Yes, In an absolute sense, it will take more time to have to parse the context. But that sounds like a case of "pre-optimization". I don't agree, because once something is in the language syntax, removing it is a long deprecation process (years), so these things have to be considered well beforehand. If we are worried about saving time then what about the tooling? compiler speed? IDE startup time? etc? All these take time too and optimizing one single aspect, as you know, won't necessarily save much time. Their speed generally does not affect the time one has to spend to understand a piece of code. Maybe the language itself should be designed so there are no ambiguities at all? A single simple for each function? A new keyboard design should be implemented(ultimately a direct brain to editor interface for the fastest time, excluding the time for development and learning)? I assume you mean "without context sensitive meanings" instead of "no ambiguities", because the latter should be the case as a matter of course (and mostly is, with few exceptions such as the dangling else ambiguity in C and friends). Assuming the former: As I stated earlier, it needs to be worth the cost. So, in this case I have to go with the practical of saying that it may be theoretically slower, but it is such an insignificant cost that it is an over optimization. I think you would agree, at least in this case. Which is why I stated I'm opposing overloading `in` here as a matter of principle, because even small costs sum up in the long run if we get into the habit of just overloading. Again, the exact syntax is not import to me. If you really think it matters that much to you and it does(you are not tricking yourself), then use a different keyword. My proposal remains to not use a keyword and just upgrade existing template specialization. When I see something I try to see it at once rather [...] To really counter your argument: What about parenthesis? They too have the same problem with in. They have perceived ambiguity... but they are not ambiguity. So your argument should be said about them too and you should be against them also, but are you? [To be clear here: foo()() and (3+4) have 3 different use cases of ()'s... The first is templated arguments, the second is function arguments, and the third is expression grouping] That doesn't counter my argument, it just states that parentheses have these costs, as well (which they do). The primary question would still be if they're worth that cost, which imho they are. Regardless of that, though, since they are already part of the language syntax (and are not going to be up for change), this is not something we could do something about, even if we agreed they weren't worth the cost. New syntax, however, is up for that kind of discussion, because once it's in it's essentially set in stone (not quite, but *very* slow to remove/change because of backwards compatibility). [...] Well, yes, as I wrote, I think it is unambiguous (and can thus be used), I just think it shouldn't be used. Yes, but you have only given the reason that it shouldn't be used because you believe that one shouldn't overload keywords because it makes it harder to parse the meaning. My rebuttal, as I have said, is that it is not harder, so your argument is not valid. All you could do is claim that it is hard and we would have to find out who is more right. As I countered that in the above, I don't think your rebuttal is valid. Well, hopefully I countered that in my rebuttal of your rebuttal of my rebuttal ;) Not as far as I see it, though I'm willing to agree to disagree :) I have a logical argument against your absolute restriction though... in that it causes one to have to use more symbols. I would imagine you are against stuff like using "in1", "in2", etc because they visibly are to close to each other. It's not an absolute restriction, it's an absolute position from which I argue against including such overloading o
Re: Bug in D!!!
On Sunday, 3 September 2017 at 11:48:38 UTC, Moritz Maxeiner wrote: On Sunday, 3 September 2017 at 04:18:03 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 02:39:19 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: [...] The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). Why? Don't you realize that the contexts matters and [...] Because instead of seeing the keyword and knowing its one meaning you also have to consider the context it appears in. That is intrinsically more work (though the difference may be very small) and thus harder. ... Yes, In an absolute sense, it will take more time to have to parse the context. But that sounds like a case of "pre-optimization". If we are worried about saving time then what about the tooling? compiler speed? IDE startup time? etc? All these take time too and optimizing one single aspect, as you know, won't necessarily save much time. Maybe the language itself should be designed so there are no ambiguities at all? A single simple for each function? A new keyboard design should be implemented(ultimately a direct brain to editor interface for the fastest time, excluding the time for development and learning)? So, in this case I have to go with the practical of saying that it may be theoretically slower, but it is such an insignificant cost that it is an over optimization. I think you would agree, at least in this case. Again, the exact syntax is not import to me. If you really think it matters that much to you and it does(you are not tricking yourself), then use a different keyword. When I see something I try to see it at once rather than reading it left to right. It is how music is read properly, for example. One can't read left to right and process the notes in real time fast enough. You must "see at once" a large chunk. When I see foo(A in B)() I see it at once, not in parts or sub-symbols(subconsciously that may be what happens, but it either is so quick or my brain has learned to see differently that I do not feel it to be any slower). that is, I do not read it like f, o, o (, A, , i,... but just like how one sees an image. Sure, there are clustering such as foo and (...), and I do sub-parse those at some point, but the context is derived very quickly. Now, of course, I do make assumptions to be able to do that. Obviously I have to sorta assume I'm reading D code and that the expression is a templated function, etc. But that is required regardless. It's like seeing a picture of an ocean. You can see the global characteristics immediately without getting bogged down in the details until you need it. You can determine the approximate time of day(morning, noon, evening, night) relatively instantaneously without even knowing much else. To really counter your argument: What about parenthesis? They too have the same problem with in. They have perceived ambiguity... but they are not ambiguity. So your argument should be said about them too and you should be against them also, but are you? [To be clear here: foo()() and (3+4) have 3 different use cases of ()'s... The first is templated arguments, the second is function arguments, and the third is expression grouping] If you are, then you are being logical and consistent, If you are not, then you are not being logical nor consistent. If you fall in the latter case, I suggest you re-evaluate the way you think about such things because you are picking and choosing. Now, if you are just stating a mathematical fast that it takes longer, then I can't really deny that, although I can't technically prove it either as you can't because we would require knowing exactly how the brain processes the information. [...] Well, yes, as I wrote, I think it is unambiguous (and can thus be used), I just think it shouldn't be used. Yes, but you have only given the reason that it shouldn't be used because you believe that one shouldn't overload keywords because it makes it harder to parse the meaning. My rebuttal, as I have said, is that it is not harder, so your argument is not valid. All you could do is claim that it is hard and we would have to find out who is more right. As I countered that in the above, I don't think your rebuttal is valid. Well, hopefully I countered that in my rebuttal of your rebuttal of my rebuttal ;) Again, you don't actually know how the brain processes information(no one does, it is all educated guesses). You use the concept that the more information one has to process the more time it takes... which seems logical, but it is not necessarily applicable directly to the interpretation of written symbols. Think of an image
Re: Bug in D!!!
On Sunday, 3 September 2017 at 04:18:03 UTC, EntangledQuanta wrote: On Sunday, 3 September 2017 at 02:39:19 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: [...] The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). Why? Don't you realize that the contexts matters and [...] Because instead of seeing the keyword and knowing its one meaning you also have to consider the context it appears in. That is intrinsically more work (though the difference may be very small) and thus harder. Again, I'm not necessarily arguing for them, just saying that one shouldn't avoid them just to avoid them. [...] It's not about ambiguity for me, it's about readability. The more significantly different meanings you overload some keyword - or symbol, for that matter - with, the harder it becomes to read. I don't think that is true. Everything is hard to read. It's about experience. The more you experience something the more clear it becomes. Only with true ambiguity is something impossible. I realize that in one can design a language to be hard to parse due to apparent ambiguities, but am I am talking about cases where they can be resolved immediately(at most a few milliseconds). Experience helps, of course, but it doesn't change that it's still just that little bit slower. And everytime we encourage such overloading encourages more, which in the end sums up. You are making general statements, and it is not that I disagree, but it depends on context(everything does). In this specific case, I think it is extremely clear what in means, so it is effectively like using a different token. Again, everyone is different though and have different experiences that help them parse things more naturally. I'm sure there are things that you might find easy that I would find hard. But that shouldn't stop me from learning about them. It makes me "smarter", to simplify the discussion. I am, because I believe it to be generally true for "1 keyword |-> 1 meaning" to be easier to read than "1 keyword and 1 context |-> 1 meaning" as the former inherently takes less time. [...] Well, yes, as I wrote, I think it is unambiguous (and can thus be used), I just think it shouldn't be used. Yes, but you have only given the reason that it shouldn't be used because you believe that one shouldn't overload keywords because it makes it harder to parse the meaning. My rebuttal, as I have said, is that it is not harder, so your argument is not valid. All you could do is claim that it is hard and we would have to find out who is more right. As I countered that in the above, I don't think your rebuttal is valid. I have a logical argument against your absolute restriction though... in that it causes one to have to use more symbols. I would imagine you are against stuff like using "in1", "in2", etc because they visibly are to close to each other. It's not an absolute restriction, it's an absolute position from which I argue against including such overloading on principle. If it can be overcome by demonstrating that it can't sensibly be done without more overloading and that it adds enough value to be worth the increases overloading, I'd be fine with inclusion. [...] I would much rather see it as a generalization of existing template specialization syntax [1], which this is t.b.h. just a superset of (current syntax allows limiting to exactly one, you propose limiting to 'n'): --- foo(T: char) // Existing syntax: Limit T to the single type `char` foo(T: (A, B, C)) // New syntax: Limit T to one of A, B, or C --- Yes, if this worked, I'd be fine with it. Again, I could care less. `:` == `in` for me as long as `:` has the correct meaning of "can be one of the following" or whatever. But AFAIK, : is not "can be one of the following"(which is "in" or "element of" in the mathematical sense) but can also mean "is a derived type of". Right, ":" is indeed an overloaded symbol in D (and ironically, instead of with "in", I think all its meanings are valuable enough to be worth the cost). I don't see how that would interfere in this context, though, as we don't actually overload a new meaning (it's still "restrict this type to the thing to the right"). If that is the case then go for it ;) It is not a concern of mine. You tell me the syntax and I will use it. (I'd have no choice, of course, but if it's short and sweet then I won't have any problem). I'm discussing this as a matter of theory, I don't have a use for it. [...] Quoting a certain person (you know who you are) from DConf 2017: "Write a DIP". I'm quite happy to discuss this idea, but at the end of t
Re: Bug in D!!!
On Sunday, 3 September 2017 at 02:39:19 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: On Saturday, 2 September 2017 at 21:19:31 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 00:00:43 UTC, EntangledQuanta wrote: On Friday, 1 September 2017 at 23:25:04 UTC, Jesse Phillips wrote: I've love being able to inherit and override generic functions in C#. Unfortunately C# doesn't use templates and I hit so many other issues where Generics just suck. I don't think it is appropriate to dismiss the need for the compiler to generate a virtual function for every instantiated T, after all, the compiler can't know you have a finite known set of T unless you tell it. But lets assume we've told the compiler that it is compiling all the source code and it does not need to compile for future linking. First the compiler will need to make sure all virtual functions can be generated for the derived classes. In this case the compiler must note the template function and validate all derived classes include it. That was easy. Next up each instantiation of the function needs a new v-table entry in all derived classes. Current compiler implementation will compile each module independently of each other; so this feature could be specified to work within the same module or new semantics can be written up of how the compiler modifies already compiled modules and those which reference the compiled modules (the object sizes would be changing due to the v-table modifications) With those three simple changes to the language I think that this feature will work for every T. Specifying that there will be no further linkage is the same as making T finite. T must be finite. C# uses generics/IR/CLR so it can do things at run time that is effectively compile time for D. By simply extending the grammar slightly in an intuitive way, we can get the explicit finite case, which is easy: foo(T in [A,B,C])() and possibly for your case foo(T in )() would work or foo(T in )() the `in` keyword makes sense here and is not used nor ambiguous, I believe. While I agree that `in` does make sense for the semantics involved, it is already used to do a failable key lookup (return pointer to value or null if not present) into an associative array [1] and input contracts. It wouldn't be ambiguous AFAICT, but having a keyword mean three different things depending on context would make the language even more complex (to read). Yes, but they are independent, are they not? Maybe not. foo(T in Typelist)() in, as used here is not a input contract and completely independent. I suppose for arrays it could be ambiguous. The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). Why? Don't you realize that the contexts matters and it's what separates the meaning? In truly unambiguous contexts, it shouldn't matter. It may require one to decipher the context, which takes time, but there is nothing inherently wrong with it and we are limited to how many symbols we use(unfortunately we are generally stuck with the querty keyboard design, else we could use symbols out the ying yang and make things much clearer, but even mathematics, which is a near perfect language, "overloads" symbols meanings). You have to do this sort of thing when you limit the number of keywords you use. Again, ultimately it doesn't matter. A symbol is just a symbol. For me, as long as the context is clear, I don't see what kind of harm it can cause. You say it is bad, but you don't give the reasons why it is bad. If you like to think of `in` has having only one definition then the question is why? You are limiting yourself. The natural languages are abound with such multi-definitions. Usually in an ambiguous way and it can cause a lot of problems, but for computer languages, it can't(else we couldn't actually compile the programs). Context sensitive grammars are provably more expressive than context free. https://en.wikipedia.org/wiki/Context-sensitive_grammar Again, I'm not necessarily arguing for them, just saying that one shouldn't avoid them just to avoid them. For me, and this is just me, I do not find it ambiguous. I don't find different meanings ambiguous unless the context overlaps. Perceived ambiguity is not ambiguity, it's just ignorance... which can be overcome through learning. Hell, D has many cases where there are perceived ambiguities... as do most things. It's not about ambiguity for me, it's about readability. The more significantly different meanings you overload some keyword - or symbol, for that matter - with, the harder it becomes to read. I don't think that is true. Everything is hard to read
Re: Bug in D!!!
On Saturday, 2 September 2017 at 23:12:35 UTC, EntangledQuanta wrote: On Saturday, 2 September 2017 at 21:19:31 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 00:00:43 UTC, EntangledQuanta wrote: On Friday, 1 September 2017 at 23:25:04 UTC, Jesse Phillips wrote: I've love being able to inherit and override generic functions in C#. Unfortunately C# doesn't use templates and I hit so many other issues where Generics just suck. I don't think it is appropriate to dismiss the need for the compiler to generate a virtual function for every instantiated T, after all, the compiler can't know you have a finite known set of T unless you tell it. But lets assume we've told the compiler that it is compiling all the source code and it does not need to compile for future linking. First the compiler will need to make sure all virtual functions can be generated for the derived classes. In this case the compiler must note the template function and validate all derived classes include it. That was easy. Next up each instantiation of the function needs a new v-table entry in all derived classes. Current compiler implementation will compile each module independently of each other; so this feature could be specified to work within the same module or new semantics can be written up of how the compiler modifies already compiled modules and those which reference the compiled modules (the object sizes would be changing due to the v-table modifications) With those three simple changes to the language I think that this feature will work for every T. Specifying that there will be no further linkage is the same as making T finite. T must be finite. C# uses generics/IR/CLR so it can do things at run time that is effectively compile time for D. By simply extending the grammar slightly in an intuitive way, we can get the explicit finite case, which is easy: foo(T in [A,B,C])() and possibly for your case foo(T in )() would work or foo(T in )() the `in` keyword makes sense here and is not used nor ambiguous, I believe. While I agree that `in` does make sense for the semantics involved, it is already used to do a failable key lookup (return pointer to value or null if not present) into an associative array [1] and input contracts. It wouldn't be ambiguous AFAICT, but having a keyword mean three different things depending on context would make the language even more complex (to read). Yes, but they are independent, are they not? Maybe not. foo(T in Typelist)() in, as used here is not a input contract and completely independent. I suppose for arrays it could be ambiguous. The contexts being independent of each other doesn't change that we would still be overloading the same keyword with three vastly different meanings. Two is already bad enough imho (and if I had a good idea with what to replace the "in" for AA's I'd propose removing that meaning). For me, and this is just me, I do not find it ambiguous. I don't find different meanings ambiguous unless the context overlaps. Perceived ambiguity is not ambiguity, it's just ignorance... which can be overcome through learning. Hell, D has many cases where there are perceived ambiguities... as do most things. It's not about ambiguity for me, it's about readability. The more significantly different meanings you overload some keyword - or symbol, for that matter - with, the harder it becomes to read. But in any case, I could care less about the exact syntax. It's just a suggestion that makes the most logical sense with regard to the standard usage of in. If it is truly unambiguous then it can be used. Well, yes, as I wrote, I think it is unambiguous (and can thus be used), I just think it shouldn't be used. Another alternative is foo(T of Typelist) which, AFAIK, of is not used in D and even most programming languages. Another could be foo(T -> Typelist) or even foo(T from Typelist) I would much rather see it as a generalization of existing template specialization syntax [1], which this is t.b.h. just a superset of (current syntax allows limiting to exactly one, you propose limiting to 'n'): --- foo(T: char) // Existing syntax: Limit T to the single type `char` foo(T: (A, B, C)) // New syntax: Limit T to one of A, B, or C --- Strictly speaking, this is exactly what template specialization is for, it's just that the current one only supports a single type instead of a set of types. Looking at the grammar rules, upgrading it like this is a fairly small change, so the cost there should be minimal. or whatever. Doesn't really matter. They all mean the same to me once the definition has been written in stone. Could use `foo(T eifjasldj Typelist)` for all I care. That's okay, but it does matter to me. The import thing for me is that such a simple syntax exists rather than the "complex syntax's" that have already been given(which are ultimately syntax's as ever
Re: Bug in D!!!
On Saturday, 2 September 2017 at 21:19:31 UTC, Moritz Maxeiner wrote: On Saturday, 2 September 2017 at 00:00:43 UTC, EntangledQuanta wrote: On Friday, 1 September 2017 at 23:25:04 UTC, Jesse Phillips wrote: I've love being able to inherit and override generic functions in C#. Unfortunately C# doesn't use templates and I hit so many other issues where Generics just suck. I don't think it is appropriate to dismiss the need for the compiler to generate a virtual function for every instantiated T, after all, the compiler can't know you have a finite known set of T unless you tell it. But lets assume we've told the compiler that it is compiling all the source code and it does not need to compile for future linking. First the compiler will need to make sure all virtual functions can be generated for the derived classes. In this case the compiler must note the template function and validate all derived classes include it. That was easy. Next up each instantiation of the function needs a new v-table entry in all derived classes. Current compiler implementation will compile each module independently of each other; so this feature could be specified to work within the same module or new semantics can be written up of how the compiler modifies already compiled modules and those which reference the compiled modules (the object sizes would be changing due to the v-table modifications) With those three simple changes to the language I think that this feature will work for every T. Specifying that there will be no further linkage is the same as making T finite. T must be finite. C# uses generics/IR/CLR so it can do things at run time that is effectively compile time for D. By simply extending the grammar slightly in an intuitive way, we can get the explicit finite case, which is easy: foo(T in [A,B,C])() and possibly for your case foo(T in )() would work or foo(T in )() the `in` keyword makes sense here and is not used nor ambiguous, I believe. While I agree that `in` does make sense for the semantics involved, it is already used to do a failable key lookup (return pointer to value or null if not present) into an associative array [1] and input contracts. It wouldn't be ambiguous AFAICT, but having a keyword mean three different things depending on context would make the language even more complex (to read). Yes, but they are independent, are they not? Maybe not. foo(T in Typelist)() in, as used here is not a input contract and completely independent. I suppose for arrays it could be ambiguous. For me, and this is just me, I do not find it ambiguous. I don't find different meanings ambiguous unless the context overlaps. Perceived ambiguity is not ambiguity, it's just ignorance... which can be overcome through learning. Hell, D has many cases where there are perceived ambiguities... as do most things. But in any case, I could care less about the exact syntax. It's just a suggestion that makes the most logical sense with regard to the standard usage of in. If it is truly unambiguous then it can be used. Another alternative is foo(T of Typelist) which, AFAIK, of is not used in D and even most programming languages. Another could be foo(T -> Typelist) or even foo(T from Typelist) or whatever. Doesn't really matter. They all mean the same to me once the definition has been written in stone. Could use `foo(T eifjasldj Typelist)` for all I care. The import thing for me is that such a simple syntax exists rather than the "complex syntax's" that have already been given(which are ultimately syntax's as everything is at the end of the day). W.r.t. to the idea in general: I think something like that could be valuable to have in the language, but since this essentially amounts to syntactic sugar (AFAICT), but I'm not (yet) convinced that with `static foreach` being included it's worth the cost. Everything is syntactic sugar. So it isn't about if but how much. We are all coding in 0's and 1's whether we realize it or not. The point if syntax(or syntactic sugar) is to reduce the amount of 0's and 1's that we have to *effectively* code by grouping common patterns in to symbolic equivalents(by definition). This is all programming is. We define certain symbols to mean certain bit patterns, or generic bit matters(an if keyword/symbol is a generic bit pattern, a set of machine instructions(0's and 1's) and substitution placeholders that are eventually filled with 0's and 1's). No one can judge the usefulness of syntax until it has been created because what determines how useful something is is its use. But you can't use something if it doesn't exist. I think many fail to get that. The initial questions should be: Is there a gap in the language? (Yes in this case). Can the gap be filled? (this is a theoretical/mathematical question that has to be answered. Most people jump the gun here and make assumptions) Does the gap need t
Re: Bug in D!!!
On Saturday, 2 September 2017 at 00:00:43 UTC, EntangledQuanta wrote: On Friday, 1 September 2017 at 23:25:04 UTC, Jesse Phillips wrote: I've love being able to inherit and override generic functions in C#. Unfortunately C# doesn't use templates and I hit so many other issues where Generics just suck. I don't think it is appropriate to dismiss the need for the compiler to generate a virtual function for every instantiated T, after all, the compiler can't know you have a finite known set of T unless you tell it. But lets assume we've told the compiler that it is compiling all the source code and it does not need to compile for future linking. First the compiler will need to make sure all virtual functions can be generated for the derived classes. In this case the compiler must note the template function and validate all derived classes include it. That was easy. Next up each instantiation of the function needs a new v-table entry in all derived classes. Current compiler implementation will compile each module independently of each other; so this feature could be specified to work within the same module or new semantics can be written up of how the compiler modifies already compiled modules and those which reference the compiled modules (the object sizes would be changing due to the v-table modifications) With those three simple changes to the language I think that this feature will work for every T. Specifying that there will be no further linkage is the same as making T finite. T must be finite. C# uses generics/IR/CLR so it can do things at run time that is effectively compile time for D. By simply extending the grammar slightly in an intuitive way, we can get the explicit finite case, which is easy: foo(T in [A,B,C])() and possibly for your case foo(T in )() would work or foo(T in )() the `in` keyword makes sense here and is not used nor ambiguous, I believe. While I agree that `in` does make sense for the semantics involved, it is already used to do a failable key lookup (return pointer to value or null if not present) into an associative array [1] and input contracts. It wouldn't be ambiguous AFAICT, but having a keyword mean three different things depending on context would make the language even more complex (to read). W.r.t. to the idea in general: I think something like that could be valuable to have in the language, but since this essentially amounts to syntactic sugar (AFAICT), but I'm not (yet) convinced that with `static foreach` being included it's worth the cost. [1] https://dlang.org/spec/expression.html#InExpression
Re: Bug in D!!!
On Saturday, 2 September 2017 at 16:20:10 UTC, Jesse Phillips wrote: On Saturday, 2 September 2017 at 00:00:43 UTC, EntangledQuanta wrote: Regardless of the implementation, the idea that we should throw the baby out with the bathwater is simply wrong. At least there are a few who get that. By looking in to it in a serious manner an event better solution might be found. Not looking at all results in no solutions and no progress. Problem is that you didn't define the problem. You showed some code the compiler rejected and expressed that the compiler needed to figure it out. You did change it to having the compiler instantiate specified types, but that isn't defining the problem. I think the problem is clearly defined, it's not my job to be a D compiler researcher and spell everything out for everyone else. Do I get paid for solving D's problems? You didn't like the code needed which would generate the functions and you hit a Visual D with the new static foreach. This sentence makes no sense. "hit a Visual D" what? Do you mean bug? If that is the case, how is that my fault? Amd I suppose to know off the bat that an access violation is caused by Visual D and not dmd when there is no info about the violation? Is it my fault that someone didn't code one of those tools good enough to express enough information for one to figure it out immediately? All of these are problems you could define, and you could have evaluated static foreach as a solution but instead stopped at problems with the tooling. Huh? I think you fail to understand the real problem. The problem has nothing to do with tooling and I never said it did. The static foreach "solution" came after the fact when SEVERAL people(ok, 2) said it was an impossible task to do. That is where all this mess started. I then came up with a solution which proved that it is possible to do on some level, that is a solution to a problem that was defined, else the solution wouldn't exist. You also don't appear to care about the complexity of the language. I expressed three required changes some of which may not play nicely with least surprise. You went straight to, we just need to define a syntax for that instead of expressing concern that the compiler will also need to handle errors to the use, such that the user understands that a feature they use is limited to very specific situations. Do you not understand that if a library solution exists then there is no real complexity added? It is called "lowering" by some. The compiler simply "rewrites" whatever new syntax is added in a form that the library solution realized. You are pretended, why?, that what I am proposed will somehow potentially affect every square micron of the D language and compiler, when it won't. Not all additions to a compiler are add *real* complexity. That is a failing of you and many on the D forums who resist change. Consider if you have a module defined interface, is that interface only available for use in that module? If not, how does a different model inherent the interface, does it need a different syntax. What does that have to do with this problem? We are not talking about interfaces. We are talking about something inside interfaces, so the problem about interfaces is irrelevant to this discussion because it applies to interfaces in general... interfaces that already exist and the problem exists regardless of what I There is a lot more to a feature then having a way to express your desires. If your going to stick to a stance that it must exist and aren't going to accept there are problems with the request why expect others to work through the request. No, your problem is your ego and your inability to interpret things outside of your own mental box. You should always keep in mind that you are interpreting someone elses mental wordage in your own way and it is not a perfect translation, in fact, we are lucky if 50% is interpreted properly. Now, if I do not have a right to express my desires, then at least state that, but I do have a right not to express any more than that. As far as motivating other people, that is isn't my job. I could care less actually. D is a hobby for me and I do it because I like the power D has, but D is the most frustrating language I have ever used. It's the most(hyperbole) buggy, most incomplete(good docs system: regardless of what the biased want to claim, tool, etc), most uninformative(errors that just toss the whole kitchen sink at you), etc. But I do have hope... which is the only reason I use it. Maybe I'm just an idiot and should go with the crowed, it would at least save me some frustration. C#, since you are familiar with it, you should know there is a huge difference. If D was like C# as far as the organizational structure(I do not mean MS, I mean the docs, library, etc) you would surely agree that D would most likely be the #1 language on this planet? C# has
Re: Bug in D!!!
On Saturday, 2 September 2017 at 00:00:43 UTC, EntangledQuanta wrote: Regardless of the implementation, the idea that we should throw the baby out with the bathwater is simply wrong. At least there are a few who get that. By looking in to it in a serious manner an event better solution might be found. Not looking at all results in no solutions and no progress. Problem is that you didn't define the problem. You showed some code the compiler rejected and expressed that the compiler needed to figure it out. You did change it to having the compiler instantiate specified types, but that isn't defining the problem. You didn't like the code needed which would generate the functions and you hit a Visual D with the new static foreach. All of these are problems you could define, and you could have evaluated static foreach as a solution but instead stopped at problems with the tooling. You also don't appear to care about the complexity of the language. I expressed three required changes some of which may not play nicely with least surprise. You went straight to, we just need to define a syntax for that instead of expressing concern that the compiler will also need to handle errors to the use, such that the user understands that a feature they use is limited to very specific situations. Consider if you have a module defined interface, is that interface only available for use in that module? If not, how does a different model inherent the interface, does it need a different syntax. There is a lot more to a feature then having a way to express your desires. If your going to stick to a stance that it must exist and aren't going to accept there are problems with the request why expect others to work through the request.
Re: Bug in D!!!
On Friday, 1 September 2017 at 23:25:04 UTC, Jesse Phillips wrote: I've love being able to inherit and override generic functions in C#. Unfortunately C# doesn't use templates and I hit so many other issues where Generics just suck. I don't think it is appropriate to dismiss the need for the compiler to generate a virtual function for every instantiated T, after all, the compiler can't know you have a finite known set of T unless you tell it. But lets assume we've told the compiler that it is compiling all the source code and it does not need to compile for future linking. First the compiler will need to make sure all virtual functions can be generated for the derived classes. In this case the compiler must note the template function and validate all derived classes include it. That was easy. Next up each instantiation of the function needs a new v-table entry in all derived classes. Current compiler implementation will compile each module independently of each other; so this feature could be specified to work within the same module or new semantics can be written up of how the compiler modifies already compiled modules and those which reference the compiled modules (the object sizes would be changing due to the v-table modifications) With those three simple changes to the language I think that this feature will work for every T. Specifying that there will be no further linkage is the same as making T finite. T must be finite. C# uses generics/IR/CLR so it can do things at run time that is effectively compile time for D. By simply extending the grammar slightly in an intuitive way, we can get the explicit finite case, which is easy: foo(T in [A,B,C])() and possibly for your case foo(T in )() would work or foo(T in )() the `in` keyword makes sense here and is not used nor ambiguous, I believe. Regardless of the implementation, the idea that we should throw the baby out with the bathwater is simply wrong. At least there are a few who get that. By looking in to it in a serious manner an event better solution might be found. Not looking at all results in no solutions and no progress.
Re: Bug in D!!!
I've love being able to inherit and override generic functions in C#. Unfortunately C# doesn't use templates and I hit so many other issues where Generics just suck. I don't think it is appropriate to dismiss the need for the compiler to generate a virtual function for every instantiated T, after all, the compiler can't know you have a finite known set of T unless you tell it. But lets assume we've told the compiler that it is compiling all the source code and it does not need to compile for future linking. First the compiler will need to make sure all virtual functions can be generated for the derived classes. In this case the compiler must note the template function and validate all derived classes include it. That was easy. Next up each instantiation of the function needs a new v-table entry in all derived classes. Current compiler implementation will compile each module independently of each other; so this feature could be specified to work within the same module or new semantics can be written up of how the compiler modifies already compiled modules and those which reference the compiled modules (the object sizes would be changing due to the v-table modifications) With those three simple changes to the language I think that this feature will work for every T.
Re: Bug in D!!!
This happens when building, not running. This might be a Visual D issue as when I use dmd from the command line, it works fine ;/
Re: Bug in D!!!
On Friday, 1 September 2017 at 19:25:53 UTC, Adam D Ruppe wrote: On Friday, 1 September 2017 at 18:17:22 UTC, EntangledQuanta wrote: I get an access violation, changed the code to What is the rest of your code? access violation usually means you didn't new the class... No, that is the code! I added nothing. Try it out and you'll see. I just upgraded to released dmd too. alias I(A...) = A; interface Foo { static foreach(T; I!(int, float)) void set(T t); // define virt funcs for a list of types } class Ass : Foo { static foreach(T; I!(int, float)) void set(T t) { // simplement } } void main() { } try it.
Re: Bug in D!!!
On Friday, 1 September 2017 at 18:17:22 UTC, EntangledQuanta wrote: I get an access violation, changed the code to What is the rest of your code? access violation usually means you didn't new the class...
Re: Bug in D!!!
On Friday, 1 September 2017 at 15:24:39 UTC, Adam D. Ruppe wrote: static foreach is now in the new release! You can now do stuff like: --- alias I(A...) = A; interface Foo { static foreach(T; I!(int, float)) void set(T t); // define virt funcs for a list of types } class Ass : Foo { static foreach(T; I!(int, float)) void set(T t) { // simplement } } --- really easily. I get an access violation, changed the code to import std.meta; static foreach(T; AliasSeq!("int", "float")) mixin("void set("~T~" t);"); and also get an access violation ;/
Re: Bug in D!!!
static foreach is now in the new release! You can now do stuff like: --- alias I(A...) = A; interface Foo { static foreach(T; I!(int, float)) void set(T t); // define virt funcs for a list of types } class Ass : Foo { static foreach(T; I!(int, float)) void set(T t) { // simplement } } --- really easily.
Re: Bug in D!!!
On Thursday, 31 August 2017 at 15:48:12 UTC, EntangledQuanta wrote: On Thursday, 31 August 2017 at 10:34:14 UTC, Kagamin wrote: On Thursday, 31 August 2017 at 00:49:22 UTC, EntangledQuanta wrote: I've already implemented a half ass library solution. It can be improved alot. Then, by all means, genius! Enjoy! mixin template virtualTemplates(alias parent, alias fn, T...) { import std.meta; alias name = Alias!(__traits(identifier, fn)[1..$]); mixin virtualTemplates!(parent, name, fn, T); } mixin template virtualTemplates(alias parent, string name, alias fn, T...) { import std.traits; static if (is(parent == interface)) { template templateOverloads(string name : name) { alias templateOverloads = T; } alias Types = T; } else { alias Types = templateOverloads!name; } mixin(virtualTemplatesImpl(name, Types.length, is(parent == class))); } string virtualTemplatesImpl(string name, int n, bool implement) { import std.format; string result; foreach (i; 0..n) { auto body = implement ? format(" { return fn!(Types[%s])(args); }", i) : ";"; result ~= format("ReturnType!(fn!(Types[%s])) %s(Parameters!(fn!(Types[%s])) args)%s\n", i, name, i, body); } return result; } interface I { void _Go(T)(T s); void _Leave(T)(T s); mixin virtualTemplates!(I, _Go, int, short, float, double); mixin virtualTemplates!(I, "Abscond", _Leave, int, short, float, double); } class C : I { void _Go(T)(T s) { } void _Leave(T)(T s) { } mixin virtualTemplates!(C, _Go); mixin virtualTemplates!(C, "Abscond", _Leave); } unittest { I c = new C(); c.Go(3.2); c.Abscond(3.4f); } Does not support multiple template parameters, or template value parameters. Use at own risk for any and all purposes.
Re: Bug in D!!!
On Thursday, 31 August 2017 at 10:34:14 UTC, Kagamin wrote: On Thursday, 31 August 2017 at 00:49:22 UTC, EntangledQuanta wrote: I've already implemented a half ass library solution. It can be improved alot. Then, by all means, genius!
Re: Bug in D!!!
On Thursday, 31 August 2017 at 00:49:22 UTC, EntangledQuanta wrote: I've already implemented a half ass library solution. It can be improved alot.
Re: Bug in D!!!
On 08/30/2017 05:49 PM, EntangledQuanta wrote: > The compiler can and should do this! Yes, the compiler can do it for each compilation but there is also the feature called /separate compilation/ that D supports. With separate compilation, there would potentially be multiple different and incompatible definitions of the same interface because compilations cannot know the whole set of instantiations of templates. This relatively popular request is impossible in D as well as other languages like C++ that practically settled on vtbl-based polymorphism. Ali
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 22:52:41 UTC, Adam D. Ruppe wrote: On Wednesday, 30 August 2017 at 20:47:12 UTC, EntangledQuanta wrote: This is quite surprising! In the new version pending release (scheduled for later this week), we get a new feature `static foreach` that will let you loop through the types you want and declare all the functions that way. When it is released, we'll have to take a second look at this problem. I've already implemented a half ass library solution. It works, but is not robust. The compiler can and should do this! string OverLoadTemplateDefinition(string name, alias func, T...)() { import std.string; string str; foreach(t; T) str ~= ((func!t).stringof).replace("function(", name~"(")~";\n"; return str; } string OverLoadTemplateMethod(string name, alias func, T...)() { import std.traits, std.algorithm, std.meta, std.string; alias RT(S) = ReturnType!(func!S); alias PN(S) = ParameterIdentifierTuple!(func!S); alias P(S) = Parameters!(func!S); alias PD(S) = ParameterDefaults!(func!S); string str; foreach(t; T) { str ~= (RT!t).stringof~" "~name~"("; foreach(k,p; P!t) { auto d = ""; static if (PD!t[k].stringof != "void") d = " = "~(PD!t)[k].stringof; str ~= p.stringof~" "~(PN!t)[k]~d; if (k < (P!t).length - 1) str ~= ", "; } str ~= ") { _"~name~"("; foreach(k, n; PN!t) { str ~= n; if (k < (P!t).length - 1) str ~= ", "; } str ~= "); }\n"; } return str; } They are basically the generic version of what Jonathan implemented by hand. In the interface: private alias _Go(T) = void function(); mixin(OverLoadTemplateDefinition!("Go", _Go, int, short, float, double)()); In class: mixin(OverLoadTemplateMethod!("Go", _Go, int, short, float, double)()); protected final void _Go(T)() { } The alias simply defines the function that we are creating. The mixin OverLoadTemplateDefinition creates the N templates. in the class, we have to do something similar but dispatch them to the protected _Go... very similar to what Jonathan did by hand. But the code to do so is not robust and will break in many cases because I left a lot of details out(linkage, attributes, etc). It is a proof of concept, and as you can see, it is not difficult. The compiler, and anyone that has a decent understanding of the internals of it, should be able to implement something quite easily. Maybe it is also possible to use OpCall to do something similar? I'd like to reiterate that this is not an insolvable problem or an NP problem. It is quite easy. If we require restricting the types to a computable set, it is just simple overloading and templatizing to reduce the complexity. Having the compiler to this can reduce the noise and increase the robustness and also provide a nice feature that it currently does not have, but should. Using templates with inheritance is a good thing, It should be allowed instead of blinding preventing all cases when only one case is uncomputable. The logic that some are using is akin to "We can't divide by 0 so lets not divide at all", but of course, division is very useful and one pathological case doesn't prevent all other cases from being useful.
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 22:08:03 UTC, Jonathan M Davis wrote: On Wednesday, August 30, 2017 21:51:57 EntangledQuanta via Digitalmars-d- learn wrote: [...] Templates have no idea what arguments you intend to use with them. You can pass them any arguments you want, and as long as they pass the template constraint, the compiler will attempt to instiate the template with those arguments - which may or may not compile, but the compiler doesn't care about that until you attempt to instantiate the template. [...] I'm going to try to implement it as a library solution, something that basically does what you have done. This will at least simplify each instance to a few lines of code but would be required in all derived classes.
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 20:47:12 UTC, EntangledQuanta wrote: This is quite surprising! In the new version pending release (scheduled for later this week), we get a new feature `static foreach` that will let you loop through the types you want and declare all the functions that way. When it is released, we'll have to take a second look at this problem.
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 22:08:03 UTC, Jonathan M Davis wrote: On Wednesday, August 30, 2017 21:51:57 EntangledQuanta via Digitalmars-d- learn wrote: The point you are trying to making, and not doing a great job, is that the compiler cannot create an unknown set of virtual functions from a single templated virtual function. BUT, when you realize that is what the problem is, the unknown set is the issue NOT templated virtual functions. Make the set known and finite somehow then you have a solution, and it's not that difficult. Just requires some elbow grease. Templates have no idea what arguments you intend to use with them. You can pass them any arguments you want, and as long as they pass the template constraint, the compiler will attempt to instiate the template with those arguments - which may or may not compile, but the compiler doesn't care about that until you attempt to instantiate the template. The language does not support a mechanism for creating a templated function where you define ahead of time what all of the legal arguments are such that the compiler will just instantiate them all for you. The compiler only instantiates templates when the code instantiates them. Feel free to open up an enhancement request for some sort of template which has a specified list of arguments to be instantiated with which the compiler will then instantiate up front and allow no others, but that is not currently a language feature. and my point is that it is not always the case that T can be anything. What if T is meant to only be algebraic? auto foo(T : Algebraic!(int, float, double))(T t){ } will the compiler be smart enough to be able to deduce that there are only 3 possibilities? No, but it should. (but of course, we don't want to use algebraic because that makes thing messy, and the whole point of all this is to reduce the mess) As far as a feature request, my guess is no one will care, I'd hope that wouldn't be the case, but seeming how much excitement in solving this problem has generated leads me to believe no one really cares about solving it. The normal solution for something like that right now would be to explicitly declare each function that you want and then have them call a templated function in order to share the implementation. e.g. class C { public: auto foo(int i) { return _foo(i); } auto foo(float f) { return _foo(f); } auto foo(string s) { return _foo(s); } private: auto _foo(T)(T T) { ...} } - Jonathan M Davis Yes, but this is really just explicit overloading. It doesn't solve the problem that templates are suppose to solve. When one starts overloading things, it becomes a bigger mess as each class needs to deal with the overloading and dispatching. It all could be solved with a bit of compiler "magic"(which should be quite simple). I mean, the compiler optimizes all kinds of things, this case shouldn't be any different. If it can determine a template parameter is reasonably finite then it should convert the templates method in to a series of overloaded methods for us... which is what you essentially did.
Re: Bug in D!!!
On Wednesday, August 30, 2017 21:51:57 EntangledQuanta via Digitalmars-d- learn wrote: > The point you are trying to making, and not doing a great job, is > that the compiler cannot create an unknown set of virtual > functions from a single templated virtual function. BUT, when you > realize that is what the problem is, the unknown set is the issue > NOT templated virtual functions. Make the set known and finite > somehow then you have a solution, and it's not that difficult. > Just requires some elbow grease. Templates have no idea what arguments you intend to use with them. You can pass them any arguments you want, and as long as they pass the template constraint, the compiler will attempt to instiate the template with those arguments - which may or may not compile, but the compiler doesn't care about that until you attempt to instantiate the template. The language does not support a mechanism for creating a templated function where you define ahead of time what all of the legal arguments are such that the compiler will just instantiate them all for you. The compiler only instantiates templates when the code instantiates them. Feel free to open up an enhancement request for some sort of template which has a specified list of arguments to be instantiated with which the compiler will then instantiate up front and allow no others, but that is not currently a language feature. The normal solution for something like that right now would be to explicitly declare each function that you want and then have them call a templated function in order to share the implementation. e.g. class C { public: auto foo(int i) { return _foo(i); } auto foo(float f) { return _foo(f); } auto foo(string s) { return _foo(s); } private: auto _foo(T)(T T) { ...} } - Jonathan M Davis
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 21:33:30 UTC, Jonathan M Davis wrote: On Wednesday, August 30, 2017 20:47:12 EntangledQuanta via Digitalmars-d- learn wrote: This is quite surprising! public struct S(T) { T s; } interface I { void Go(T)(S!T s); static final I New() { return new C(); } } abstract class A : I { } class C : A { void Go(T)(S!T s) { } } void main() { S!int s; auto c = I.New(); c.Go(s);// fails! //(cast(C)c).Go(s); // Works, only difference is we have made c an explicit C. } https://dpaste.dzfl.pl/dbc5a0663802 Everything works when Go is not templatized(we explicitly make T an int) This is a blocker for me! Can someone open a ticket? It is not possible to have a function be both virtual and templated. A function template generates a new function definition every time that it's a called with a new set of template arguments. So, the actual functions are not known up front, and that fundamentally does not work with virtual functions, where the functions need to be known up front, and you get a different function by a look-up for occurring in the virtual function call table for the class. Templates and virtual functions simply don't mix. You're going to have to come up with a solution that does not try and mix templates and virtual functions. - Jonathan M Davis I have a finite number of possible values of T, lets say 3. They are known at compile time, just because you are or D thinks they are not simply means you or D is not trying hard enough. So, saying that virtual methods and templates are not compatible is wrong. Just because you think they are or D thinks they are means you haven't thought about it hard enough. If I can overload a virtual function to get all my use cases and that is all I need then I **should** be able to do it with templates. Simple as that, if D can't do that then D needs to be enhanced to do so. e.g., class C { Go(Primitive!T)(T t); } The compiler can realize that T can only be a primitive, and generates all possible combinations of primitives, which is finite. This is doable, it is not impossible, regardless of what you think. It is equivalent to class C { Go(Primitive1 t); Go(Primitive2 t); ... Go(PrimitiveN t); } In fact, we can use string mixins to generate such code, but it doens't save us trouble, which is what templates are suppose to do in the first place. Just become someone hasn't implemented special cases does not mean it is theoretically impossible to do. A different syntax would be better interface I { Go(T in [float, double, int])(T t); } class C : I { Go(T in [float, double, int])(T t) { } } which the compiler "unrolls" to interface I { Go(float t); Go(double t); Go(int t); } class C { Go(float t) { } Go(double t) { } Go(int t) { } } Which, is standard D code. There is nothing wrong with specializing the most common cases. The point you are trying to making, and not doing a great job, is that the compiler cannot create an unknown set of virtual functions from a single templated virtual function. BUT, when you realize that is what the problem is, the unknown set is the issue NOT templated virtual functions. Make the set known and finite somehow then you have a solution, and it's not that difficult. Just requires some elbow grease. Primitives are obviously known at compile time so that is a doable special case. Although there will probably be quite a bit of wasted space since each primitive will have a function generated for it for each templated function, that really isn't an issue. By adding a new syntax in D, we could allow for any arbitrary(but known and finite) set to be used Go(T in [A,B,C])(T t) Where A,B,C are known types at compile time. This generates 3 functions and is doable. (should be simple for any D compiler genius to add for testing)
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 20:47:12 UTC, EntangledQuanta wrote: This is quite surprising! public struct S(T) { T s; } interface I { void Go(T)(S!T s); static final I New() { return new C(); } } abstract class A : I { } class C : A { void Go(T)(S!T s) { } } void main() { S!int s; auto c = I.New(); c.Go(s);// fails! //(cast(C)c).Go(s); // Works, only difference is we have made c an explicit C. } https://dpaste.dzfl.pl/dbc5a0663802 Everything works when Go is not templatized(we explicitly make T an int) This is a blocker for me! Can someone open a ticket? Knock yourself out: https://issues.dlang.org/ Anyone can open tickets for bugs or enhancement requsts. bye, lobo
Re: Bug in D!!!
On Wednesday, 30 August 2017 at 21:13:19 UTC, Kagamin wrote: It can't work this way. You can try std.variant. Sure it can! What are you talking about! std.variant has nothing to do with it! It works if T is hard coded, so it should work generically. What's the point of templates variables if they can't be used across inheritance? I could overload Go for each type and hence it should work. There is absolutely no reason why it can't work. Replace T with short, it works, replace T with anything and it works, hence it should work with T. If you are claiming that the compiler has to make a virtual function for each T, that is nonsense, I only need it for primitives, and there are a finite number of them. I could create overloads for short, int, double, float, etc but why? The whole point of templates is to solve that problem. Variants do not help. Openmethods can solve this problem too, but D should be more intelligent than simply writing off all normal use cases because someone thinks something can't be done. How many people thought it was impossible to go to the moon, yet it happened. Anyone can't deny anything, it's such a simple thing to do...
Re: Bug in D!!!
On Wednesday, August 30, 2017 20:47:12 EntangledQuanta via Digitalmars-d- learn wrote: > This is quite surprising! > > public struct S(T) > { > T s; > } > > > interface I > { > void Go(T)(S!T s); > > static final I New() > { > return new C(); > } > } > > abstract class A : I > { > > } > > > class C : A > { > void Go(T)(S!T s) > { > > } > } > > > void main() > { > S!int s; > auto c = I.New(); > > c.Go(s);// fails! > //(cast(C)c).Go(s); // Works, only difference is we have made c > an explicit C. > > } > > https://dpaste.dzfl.pl/dbc5a0663802 > > Everything works when Go is not templatized(we explicitly make T > an int) > > > This is a blocker for me! Can someone open a ticket? It is not possible to have a function be both virtual and templated. A function template generates a new function definition every time that it's a called with a new set of template arguments. So, the actual functions are not known up front, and that fundamentally does not work with virtual functions, where the functions need to be known up front, and you get a different function by a look-up for occurring in the virtual function call table for the class. Templates and virtual functions simply don't mix. You're going to have to come up with a solution that does not try and mix templates and virtual functions. - Jonathan M Davis
Re: Bug in D!!!
It can't work this way. You can try std.variant.
Bug in D!!!
This is quite surprising! public struct S(T) { T s; } interface I { void Go(T)(S!T s); static final I New() { return new C(); } } abstract class A : I { } class C : A { void Go(T)(S!T s) { } } void main() { S!int s; auto c = I.New(); c.Go(s);// fails! //(cast(C)c).Go(s); // Works, only difference is we have made c an explicit C. } https://dpaste.dzfl.pl/dbc5a0663802 Everything works when Go is not templatized(we explicitly make T an int) This is a blocker for me! Can someone open a ticket?
Re: C callbacks getting a value of 0! Bug in D?
On 8/28/17 9:34 PM, Johnson Jones wrote: produces 4 on both x86 and x64. So, I'm not sure how you are getting 8. Yes, this is exactly why you should use c_long and c_ulong, because just using int makes it not portable to other systems. -Steve
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 02:47:34 UTC, Johnson Jones wrote: [...] Seems only long and ulong are issues. With respect to the currently major platforms you can reasonable expect software to run on, yes. Just don't try to use D on something with e.g. 32 bit C shorts unless you bind to it via c_short.
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 01:56:43 UTC, Moritz Maxeiner wrote: On Tuesday, 29 August 2017 at 01:34:40 UTC, Johnson Jones wrote: [...] produces 4 on both x86 and x64. So, I'm not sure how you are getting 8. There are different 64bit data models [1] and it seems your platform uses LLP64, which uses 32bit longs. Am I correct in assuming you're on Windows (as they are the only major modern platform that I'm aware of that made this choice)? [1] https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models Yes. I found this, which gives a map for all the types: https://dlang.org/spec/interfaceToC.html Seems only long and ulong are issues.
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 01:34:40 UTC, Johnson Jones wrote: import core.stdc.config; pragma(msg, c_long.sizeof); prints 4UL both on x64 and x86 and and C: void foo() { int dummy; switch (dummy) { case sizeof(long) : case sizeof(long) : break; } } produces 4 on both x86 and x64. So, I'm not sure how you are getting 8. It's because you're on Windows. There, long/ulong are 4 bytes in both 32- and 64-bit. On Linux/Mac/*BSD, they're 4 in 32-bit and 8 in 64-bit. This is why we have c_long and c_ulong, to hide those differences.
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 01:34:40 UTC, Johnson Jones wrote: [...] produces 4 on both x86 and x64. So, I'm not sure how you are getting 8. There are different 64bit data models [1] and it seems your platform uses LLP64, which uses 32bit longs. Am I correct in assuming you're on Windows (as they are the only major modern platform that I'm aware of that made this choice)? [1] https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
Re: C callbacks getting a value of 0! Bug in D?
On Tuesday, 29 August 2017 at 00:42:45 UTC, Steven Schveighoffer wrote: On 8/28/17 7:47 PM, Johnson Jones wrote: [...] Then I think possibly the port audio bindings are not correct. It's also possible that long is not 64-bit even on the platform you are using. Finally, it's also possible that the D compiler is not generating the call correctly. When I test on my mac, c_long is 8-bytes. I'm not sure what it is in your case, try this code and see what happens: import core.stdc.config; pragma(msg, c_long.sizeof); // prints 8 on my box. And in c: #include int main() { printf("%lu\n", sizeof(long)); // also prints 8 on my box return 0; } They should match. If they don't, that's a D bug (in either core.stdc.config or the compiler, I'm not sure which). If they do, then one of the other two possibilities is happening, and I would lean towards the bindings being incorrect. -Steve import core.stdc.config; pragma(msg, c_long.sizeof); prints 4UL both on x64 and x86 and and C: void foo() { int dummy; switch (dummy) { case sizeof(long) : case sizeof(long) : break; } } produces 4 on both x86 and x64. So, I'm not sure how you are getting 8.
Re: C callbacks getting a value of 0! Bug in D?
On 8/28/17 7:47 PM, Johnson Jones wrote: On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote: On 8/27/17 10:17 PM, Johnson Jones wrote: Looking at the assembly shows something like this: 0041ea98 push 0x0 0041ea9a push 0x0 0041ea9c push 0x0 0041ea9e push dword 0x100 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] 0041eaa9 mov eax, [fs:0x2c] 0041eaaf mov edx, [eax+ecx*4] 0041eab2 push dword [edx+0x1c] 0041eab8 push dword [edx+0x18] 0041eabe push dword [ebp-0x54] 0041eac1 push dword [ebp-0x5c] 0041eac4 mov ebx, PA.stream (0x823f30) 0041eac9 push ebx 0041eaca call dword near [Pa_OpenStream (0x823f18)] I noticed that those 0's were the values being fed in to the function. I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... Anyways, At least I'm on the right track. For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing). In portaudio, this doesn't seem to be the case. I changed all the longs to ints and ran my code in x64 and it worked fine. It may just be that the stuff that uses long is not used in my code. In port audio I see it using unsigned long and so this should be 64-bits in x64. Surprised it worked. Maybe conversion is taking place or the high bits of the long are 0'ed and so there is not much difference. Then I think possibly the port audio bindings are not correct. It's also possible that long is not 64-bit even on the platform you are using. Finally, it's also possible that the D compiler is not generating the call correctly. When I test on my mac, c_long is 8-bytes. I'm not sure what it is in your case, try this code and see what happens: import core.stdc.config; pragma(msg, c_long.sizeof); // prints 8 on my box. And in c: #include int main() { printf("%lu\n", sizeof(long)); // also prints 8 on my box return 0; } They should match. If they don't, that's a D bug (in either core.stdc.config or the compiler, I'm not sure which). If they do, then one of the other two possibilities is happening, and I would lean towards the bindings being incorrect. -Steve
Re: C callbacks getting a value of 0! Bug in D?
On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote: On 8/27/17 10:17 PM, Johnson Jones wrote: Looking at the assembly shows something like this: 0041ea98 push 0x0 0041ea9a push 0x0 0041ea9c push 0x0 0041ea9e push dword 0x100 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] 0041eaa9 mov eax, [fs:0x2c] 0041eaaf mov edx, [eax+ecx*4] 0041eab2 push dword [edx+0x1c] 0041eab8 push dword [edx+0x18] 0041eabe push dword [ebp-0x54] 0041eac1 push dword [ebp-0x5c] 0041eac4 mov ebx, PA.stream (0x823f30) 0041eac9 push ebx 0041eaca call dword near [Pa_OpenStream (0x823f18)] I noticed that those 0's were the values being fed in to the function. I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... Anyways, At least I'm on the right track. For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing). -Steve In portaudio, this doesn't seem to be the case. I changed all the longs to ints and ran my code in x64 and it worked fine. It may just be that the stuff that uses long is not used in my code. In port audio I see it using unsigned long and so this should be 64-bits in x64. Surprised it worked. Maybe conversion is taking place or the high bits of the long are 0'ed and so there is not much difference. Anyways, I guess I'll deal with any of those bugs when I run in to them, if they exist.
Re: C callbacks getting a value of 0! Bug in D?
On Monday, 28 August 2017 at 22:41:56 UTC, Moritz Maxeiner wrote: On Monday, 28 August 2017 at 22:21:18 UTC, Johnson Jones wrote: On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote: [...] and where are these c_ types defined? The reason I replaced them was precisely because D was not finding them. core.stdc.config , which unfortunately doesn't appear in the online documentation AFAICT (something that ought to be fixed). A common workaround is to use pattern searching tools like grep if you know the phrase to look for: $ grep -Er c_long /path/to/imports , or in this case, since these things are usually done with aliases: $ grep -Er 'alias\s+\w*\s+c_long' /path/to/imports Thanks. I copied over stuff from the bindings and from the original header and I guess I missed the import.
Re: C callbacks getting a value of 0! Bug in D?
On Monday, 28 August 2017 at 22:21:18 UTC, Johnson Jones wrote: On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote: On 8/27/17 10:17 PM, Johnson Jones wrote: [...] For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing). -Steve and where are these c_ types defined? The reason I replaced them was precisely because D was not finding them. core.stdc.config , which unfortunately doesn't appear in the online documentation AFAICT (something that ought to be fixed). A common workaround is to use pattern searching tools like grep if you know the phrase to look for: $ grep -Er c_long /path/to/imports , or in this case, since these things are usually done with aliases: $ grep -Er 'alias\s+\w*\s+c_long' /path/to/imports
Re: C callbacks getting a value of 0! Bug in D?
On Monday, 28 August 2017 at 21:35:27 UTC, Steven Schveighoffer wrote: On 8/27/17 10:17 PM, Johnson Jones wrote: [...] For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing). -Steve and where are these c_ types defined? The reason I replaced them was precisely because D was not finding them.
Re: C callbacks getting a value of 0! Bug in D?
On 8/27/17 10:17 PM, Johnson Jones wrote: Looking at the assembly shows something like this: 0041ea98 push 0x0 0041ea9a push 0x0 0041ea9c push 0x0 0041ea9e push dword 0x100 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] 0041eaa9 mov eax, [fs:0x2c] 0041eaaf mov edx, [eax+ecx*4] 0041eab2 push dword [edx+0x1c] 0041eab8 push dword [edx+0x18] 0041eabe push dword [ebp-0x54] 0041eac1 push dword [ebp-0x5c] 0041eac4 mov ebx, PA.stream (0x823f30) 0041eac9 push ebx 0041eaca call dword near [Pa_OpenStream (0x823f18)] I noticed that those 0's were the values being fed in to the function. I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... Anyways, At least I'm on the right track. For C/C++ interaction, always use c_... types if they are available. The idea is both that they will be correctly defined for the width, and also it will mangle correctly for C++ compilers (yes, long and int are mangled differently even when they are the same thing). -Steve
Re: C callbacks getting a value of 0! Bug in D?
Looking at the assembly shows something like this: 0041ea98 push 0x0 0041ea9a push 0x0 0041ea9c push 0x0 0041ea9e push dword 0x100 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] 0041eaa9 mov eax, [fs:0x2c] 0041eaaf mov edx, [eax+ecx*4] 0041eab2 push dword [edx+0x1c] 0041eab8 push dword [edx+0x18] 0041eabe push dword [ebp-0x54] 0041eac1 push dword [ebp-0x5c] 0041eac4 mov ebx, PA.stream (0x823f30) 0041eac9 push ebx 0041eaca call dword near [Pa_OpenStream (0x823f18)] I noticed that those 0's were the values being fed in to the function. I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... Anyways, At least I'm on the right track.
C callbacks getting a value of 0! Bug in D?
Trying to set a callback for portaudio and it's seeing zero for the value passed. Pa_OpenStream(&stream, input, output, sampleRate, cast(ulong)0, cast(PaStreamFlags)(PaStreamFlags.NoFlag + 0*PaStreamFlags.PrimeOutputBuffersUsingStreamCallback), cast(PaStreamCallback)(a,b,c,d,e,f){ callbackCalled = true; return 0; }, null); I am using a debug build of portaudio that prints out all the parameters before anything else, so it's not an issue with portaudio. I've tried passing a normal function: __gshared int sawtooth(const(void)* inputBuffer, void* outputBuffer, ulong framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { return 0; } and passing it as &sawtooth. with the same issue. I've tried changing the calling convention and using __gshared but the value is always 0. It seems other values are 0 too and can't seem to get any value in to the callback(Even a random one). The output essentially always looks like this: Opening Stream! Pa_OpenStream called: PaStream** stream: 0x00823EA0 PaStreamParameters *inputParameters: NULL PaStreamParameters *outputParameters: 0x02C6C1C0 PaDeviceIndex outputParameters->device: 3 int outputParameters->channelCount: 4 PaSampleFormat outputParameters->sampleFormat: 1 PaTime outputParameters->suggestedLatency: 0.135000 void *outputParameters->hostApiSpecificStreamInfo: 0x double sampleRate: 44100 unsigned long framesPerBuffer: 256 PaStreamFlags streamFlags: 0x0 PaStreamCallback *streamCallback: 0x void *userData: 0x Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 1 Pa_GetSampleSize returned: int: 4 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_OpenStream returned: *(PaStream** stream): 0x03BEAD50 PaError: 0 ( Success ) everything seems correct except: PaStreamCallback *streamCallback: 0x void *userData: 0x You can find the full code at https://forum.dlang.org/thread/lkbswgpsgxynhfyzw...@forum.dlang.org This is either a bug in D, an issue with calling conventions, or how one passes the data. The original portaudio open stream function, so you can see that it simply prints it's arguments: PaError Pa_OpenStream( PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ) { PaError result; PaUtilHostApiRepresentation *hostApi = 0; PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice; PaStreamParameters hostApiInputParameters, hostApiOutputParameters; PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr; #ifdef PA_LOG_API_CALLS PA_LOGAPI_ENTER_PARAMS( "Pa_OpenStream" ); PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream )); if( inputParameters == NULL ){ PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" )); }else{ PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters )); PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device )); PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount )); PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat )); PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency )); PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo )); } if( outputParameters == NULL ){ PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" )); }else{ PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters ));
Re: Bug in D?!
On Fri, Aug 11, 2017 at 11:34:04PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: > On Friday, 11 August 2017 at 22:43:02 UTC, Mr. Pib wrote: > > int and I should be able to append an int without having to worry > > about the value of the int. > > Appending an int to a string really ought to just be a type mismatch error. > > We might be able to convince the leadership to do that too, since that > still fits with the C compatibility guidelines. I support this. Changing the behaviour silently is definitely a no-go, but I'm all for breaking code with wrong or questionable behaviour. Unfortunately, I'm not sure how likely it is to convince W & A about this one... they have previously shown resistance to changing char to int promotion rules, even though it has caused grief elsewhere. T -- One Word to write them all, One Access to find them, One Excel to count them all, And thus to Windows bind them. -- Mike Champion
Re: Bug in D?!
On Friday, 11 August 2017 at 23:34:04 UTC, Adam D. Ruppe wrote: On Friday, 11 August 2017 at 22:43:02 UTC, Mr. Pib wrote: int and I should be able to append an int without having to worry about the value of the int. Appending an int to a string really ought to just be a type mismatch error. We might be able to convince the leadership to do that too, since that still fits with the C compatibility guidelines. I'd prefer that since at least it wouldn't silently work and produce potentially catastrophic errors. But then that too is still breaking backwards compatibility(which I think is the plague of the 21st century).
Re: Bug in D?!
On Friday, 11 August 2017 at 22:43:02 UTC, Mr. Pib wrote: int and I should be able to append an int without having to worry about the value of the int. Appending an int to a string really ought to just be a type mismatch error. We might be able to convince the leadership to do that too, since that still fits with the C compatibility guidelines.
Re: Bug in D?!
On Friday, 11 August 2017 at 22:50:53 UTC, ketmar wrote: Mr. Pib wrote: Wow, that is pretty screwed up! I thought D was against implicit conversions that might cause problems? I'm passing an int and I should be able to append an int without having to worry about the value of the int. Instead D chose to do something very strange, awkward, and error prone. this is legacy we got from trying to be C-compatible (along with int/uint autoconversion, and some other things). i believe that initially it was done to allow something like `char c = 32;`, and now it is too late to change it, 'cause such change will break existing code (and we're trying to not break the code without a *very* strong reason, even if keeping old code working means keeping some old quirks). The problem is that that mentality perpetuates the problem. It keeps things from ever getting fixed and corrected by it's very nature... all to supposedly save time but how much time does it waste too? It would be better to break things cleanly and let those that get errors fix them... cause hell, after some years the old code will not be used more anyways or be rewritten so maybe it is trying to solve a problem that doesn't actually exist?
Re: Bug in D?!
Mr. Pib wrote: Wow, that is pretty screwed up! I thought D was against implicit conversions that might cause problems? I'm passing an int and I should be able to append an int without having to worry about the value of the int. Instead D chose to do something very strange, awkward, and error prone. this is legacy we got from trying to be C-compatible (along with int/uint autoconversion, and some other things). i believe that initially it was done to allow something like `char c = 32;`, and now it is too late to change it, 'cause such change will break existing code (and we're trying to not break the code without a *very* strong reason, even if keeping old code working means keeping some old quirks).
Re: Bug in D?!
On Friday, 11 August 2017 at 04:17:32 UTC, ketmar wrote: Mr. Pib wrote: string Q(alias T, alias D)() { pragma(msg, T); pragma(msg, D); enum x = T~" = "~D~";"; pragma(msg, x); } mixin(Q!(`x`, 100)()); outputs, at compile time, x 100 x = d; there is no lowercase d. I did initially define Q as string Q(alias T, D)(D d) and one might think it is remnants left over from I cleaned the project so it shouldn't be happening. Seems like a bug. (I realized that I'd probably only ever pass compile time values) Of course, using D.stringof gives the value. The problem is the case of D. nope. the problem is the *value* of D. `char(100)` == 'd'. string s = "<"~100~">"; yes, this works. weither this bug or not is questionable, but this is how D works regerding to implicit type conversions: small ints (in the range of [0..char.max]) will be implicitly converted to `char` if necessary. Wow, that is pretty screwed up! I thought D was against implicit conversions that might cause problems? I'm passing an int and I should be able to append an int without having to worry about the value of the int. Instead D chose to do something very strange, awkward, and error prone.
Re: Bug in D?!
Mr. Pib wrote: string Q(alias T, alias D)() { pragma(msg, T); pragma(msg, D); enum x = T~" = "~D~";"; pragma(msg, x); } mixin(Q!(`x`, 100)()); outputs, at compile time, x 100 x = d; there is no lowercase d. I did initially define Q as string Q(alias T, D)(D d) and one might think it is remnants left over from I cleaned the project so it shouldn't be happening. Seems like a bug. (I realized that I'd probably only ever pass compile time values) Of course, using D.stringof gives the value. The problem is the case of D. nope. the problem is the *value* of D. `char(100)` == 'd'. string s = "<"~100~">"; yes, this works. weither this bug or not is questionable, but this is how D works regerding to implicit type conversions: small ints (in the range of [0..char.max]) will be implicitly converted to `char` if necessary.
Bug in D?!
string Q(alias T, alias D)() { pragma(msg, T); pragma(msg, D); enum x = T~" = "~D~";"; pragma(msg, x); } mixin(Q!(`x`, 100)()); outputs, at compile time, x 100 x = d; there is no lowercase d. I did initially define Q as string Q(alias T, D)(D d) and one might think it is remnants left over from I cleaned the project so it shouldn't be happening. Seems like a bug. (I realized that I'd probably only ever pass compile time values) Of course, using D.stringof gives the value. The problem is the case of D.