const of AliasSeq is silently ignored
In this example: const(AliasSeq!(int, int)) a; pragma(msg, typeof(a)); // (int, int) This kind of make sense, since AliasSeq is not a "single" type. But silently dropping const seems bad, the compiler should probably report an error/warning in this case?
ElementType of MapResult is a delegate??
This surprised me A LOT: https://d.godbolt.org/z/82a_GZ So if I call something.map!().array, I get an array of delegates? That makes no sense to me.
Re: Circular reference error gone after inspecting members
Issue filed: https://issues.dlang.org/show_bug.cgi?id=19190
Suggestion: Bug fix releases (Re: Dicebot on leaving D: It is anarchy driven development in all its glory.)
On Wednesday, 22 August 2018 at 11:59:37 UTC, Paolo Invernizzi wrote: Just found by chance, if someone is interested [1] [2]. /Paolo [1] https://gitlab.com/mihails.strasuns/blog/blob/master/articles/on_leaving_d.md [2] https://blog.mist.global/articles/My_concerns_about_D_programming_language.html I find Dicebot's article resonates quite strongly with me. I have been using D for hobby projects (i.e. not a lot of code) for about 3 years. During that time I found a handful of compiler bugs. An average programmer like me shouldn't be able to find bugs in the compiler so frequently. And there are other problems, like language features interact weirdly, unhelpful/misleading error messages. All of this really gives me an impression that D is an immature language. I think this is a pretty big problem, and I think it has not been given enough attention (never appeared in bold in the vision documents), probably until now. So what if, we just forget about @safe, @nogc, and stuff like that for while, do a feature freeze and try our best to fix all the bugs, and rough corners?
Re: Circular reference error gone after inspecting members
On Saturday, 25 August 2018 at 14:13:18 UTC, rikki cattermole wrote: On 26/08/2018 2:10 AM, Yuxuan Shui wrote: The offending code base is a little big and hard to reduce. I'll try if code is required, but here is the gist of the problem: This snippet of code in my project: ... alias tmp = genCode!T; enum str = tmp.str; // This line here ... Generate a circular reference error. However, if I do: ... alias tmp = genCode!T; pragma(msg, __traits(allMembers, tmp)); enum str = tmp.str; // This line here ... Then the error is gone. Anyone has any idea what could the problem be? If that pragma(msg) does indeed make it disappear (check -v to confirm), then its a bug. Alright then. I'll spend sometime and see if I can make a minimal example.
Circular reference error gone after inspecting members
The offending code base is a little big and hard to reduce. I'll try if code is required, but here is the gist of the problem: This snippet of code in my project: ... alias tmp = genCode!T; enum str = tmp.str; // This line here ... Generate a circular reference error. However, if I do: ... alias tmp = genCode!T; pragma(msg, __traits(allMembers, tmp)); enum str = tmp.str; // This line here ... Then the error is gone. Anyone has any idea what could the problem be?
Re: Alignment of symbol is not kept during linking
On Friday, 10 August 2018 at 08:46:46 UTC, Kagamin wrote: On Thursday, 9 August 2018 at 14:15:31 UTC, Yuxuan Shui wrote: The alignment is specified for the section, and it apparently kept. problem is individual symbols in the section don't have a alignment. If the section is aligned at 16 bytes and the symbol is aligned at 16 bytes in the section, then the symbol will be aligned at 16 bytes, I don't thunk this can go wrong. I think you are correct. And I finally found out what is the culprit: The section is not actually aligned. Bug report: https://issues.dlang.org/show_bug.cgi?id=19148
Re: Alignment of symbol is not kept during linking
On Thursday, 9 August 2018 at 13:50:00 UTC, Kagamin wrote: On Thursday, 9 August 2018 at 13:30:38 UTC, Yuxuan Shui wrote: I searched around, and there seems to be no way to specify alignment on symbol, so I don't think the linker is in the wrong here. The alignment should be specified for section. The alignment is specified for the section, and it apparently kept. problem is individual symbols in the section don't have a alignment.
Re: Alignment of symbol is not kept during linking
Clarifications: On Thursday, 9 August 2018 at 13:30:38 UTC, Yuxuan Shui wrote: I'm trying to build LDC with dmd and Musl, but the result ldc will always crash. I track that down to an unalignment SIMD access to a global variable. Apparently C++ compiler thinks the variable should be aligned to 16 bytes, but it's only aligned to 8 bytes. SIMD is generated by the C++ compiler, the unaligned read happens in C++ code. The accessed variable is a __gshared global variable.
Alignment of symbol is not kept during linking
I'm trying to build LDC with dmd and Musl, but the result ldc will always crash. I track that down to an unalignment SIMD access to a global variable. Apparently C++ compiler thinks the variable should be aligned to 16 bytes, but it's only aligned to 8 bytes. After some more digging, I find out dmd does try to do the right thing here. In the .o file, the offending symbol is indeed aligned to 16 bytes. But, after linking, that symbol got bumped 8 bytes for some reason. I searched around, and there seems to be no way to specify alignment on symbol, so I don't think the linker is in the wrong here. C compilers would not put variables like that in .data, instead they use SHN_COMMON, and specify alignment there. LDC will just put every symbol into their own section, which also supports alignment. dmd should probably do the same.
getProtection gives different result when member is accessed via getMember
file1.d: import std.stdio; file2.d: import file1; pragma(msg, __traits(getProtection, __traits(getMember, m1, "std"))); // public pragma(msg, __traits(getProtection, m1.std)); // private Bug? Intended?
Re: Eponymous template member from a template mixin
On Saturday, 4 August 2018 at 21:10:32 UTC, Steven Schveighoffer wrote: On 8/4/18 4:10 PM, Yuxuan Shui wrote: This doesn't work: template A() { void B() {}; } template B() { mixin A!(); } void main() { B!()(); } Is this intentional? I believe mixin templates introduce a new symbol namespace to a degree. I doubt you would be able to do something like this. -Steve What is the rational behind this?
Eponymous template member from a template mixin
This doesn't work: template A() { void B() {}; } template B() { mixin A!(); } void main() { B!()(); } Is this intentional?
Re: A struct with a tuple as alias this, is kind of confusing
On Friday, 27 July 2018 at 10:48:08 UTC, ag0aep6g wrote: On 07/27/2018 12:19 PM, Yuxuan Shui wrote: On Friday, 27 July 2018 at 10:17:21 UTC, Yuxuan Shui wrote: [...] Oh no, is it just defining arrays in the is() statement, though? Yup. But wait, this works: alias C = A!(1,2,3); static if (C[0] < C[1]) pragma(msg, "Ha!"); Looks like DMD decides that `C[0]` and `C[1]` can't be types in that situation, so it tries the alias this. That's in line with how alias this is supposed to work: only kick in when the code wouldn't compile otherwise. Let's just say this is confusing as hell.
Re: A struct with a tuple as alias this, is kind of confusing
On Friday, 27 July 2018 at 10:17:21 UTC, Yuxuan Shui wrote: First, it surprised me that I can't index a struct like that. So: struct A(T...) { alias S = T; alias S this; } alias B = A!(int, double); B[0] x; // Actually an array Then, it surprised me again, that I actually can index it, sometimes static if (!is(B[0] == B[1])) pragma(msg, "Works!"); Why is this language like this :( Oh no, is it just defining arrays in the is() statement, though? But wait, this works: alias C = A!(1,2,3); static if (C[0] < C[1]) pragma(msg, "Ha!");
A struct with a tuple as alias this, is kind of confusing
First, it surprised me that I can't index a struct like that. So: struct A(T...) { alias S = T; alias S this; } alias B = A!(int, double); B[0] x; // Actually an array Then, it surprised me again, that I actually can index it, sometimes static if (!is(B[0] == B[1])) pragma(msg, "Works!"); Why is this language like this :(
Re: I have a plan.. I really DO
On Friday, 6 July 2018 at 21:15:46 UTC, H. S. Teoh wrote: On Fri, Jul 06, 2018 at 08:16:36PM +, Ecstatic Coder via Digitalmars-d-announce wrote: [...] I've never said that this is something smart to do. I'm just saying that this code can perfectly be executed once in a C++ game frame without having to worry for a game freeze, because the string buffer deallocation is done once per frame too. While with many GC languages, you actually DON'T KNOW when all those unused string buffers will be claimed. [...] Of course, for someone looking for an excuse not to use D, they will always find another reason why this is not sufficient. But that only strengthens the point that the GC is just a convenient excuse not to use D. Not a good excuse to not fix GC, though. Solve that problem, and they will just move on to the next excuse, because the GC is not the real reason; the real reason is probably non-technical. Like good ole inertia: people are lazy and set in their ways, and resist changing what they've grown comfortable with. But actually admitting this would make them look bad, so it is easier to find a convenient excuse like the GC (or whatever else is different from the status quo). If that's the case, then we are doom. We might just as well forget about getting popular, and instead spend time making the language better. Like fixing the GC. (Although I don't quite agree with you. Some people DO resist change, that's why some decades old languages are still popular. But look at the popularity of new languages like Go, and Rust, and the ever-change landscape of front-end development. There're tons of people who adapt certain technology just because it is new, why can't that happen to D?) T
Re: Normalize void
On Tuesday, 10 July 2018 at 11:37:25 UTC, ag0aep6g wrote: On 07/10/2018 11:56 AM, Yuxuan Shui wrote: Possible alternatives: * struct Void {}. Takes 1 byte, not as ideal * alias Void = AliasSeq!(). Doesn't work as template argument. i.e. SomeTemplate!Void; // actually become SomeTemplate!() What about `void[0]`? It's a proper type. You can declare a field with it. Size is 0. Nice!
Re: Normalize void
On Tuesday, 10 July 2018 at 09:50:45 UTC, Yuxuan Shui wrote: Suppose I want to create a type to contain either a return value or an error, I could probably do something like this: [...] Breaking changes: void[] x; pragma(msg, x[0].sizeof); // now 0?
Re: Normalize void
On Tuesday, 10 July 2018 at 09:50:45 UTC, Yuxuan Shui wrote: Suppose I want to create a type to contain either a return value or an error, I could probably do something like this: [...] Possible alternatives: * struct Void {}. Takes 1 byte, not as ideal * alias Void = AliasSeq!(). Doesn't work as template argument. i.e. SomeTemplate!Void; // actually become SomeTemplate!()
Normalize void
Suppose I want to create a type to contain either a return value or an error, I could probably do something like this: struct Result(T, E) { bool is_err; union { T result; E error; } } This will probably work fine, unless I don't need an error for some of the use cases (i.e. I want it to behave more like a Nullable). I can't just pass 'void' to 'E', because I can't define variable with type void. So I will have to: struct Result(T, E) { bool is_err; union { T result; static if (!is(E == void)) E error; } } I hope you can see what I mean here: 'void' is a special case I need to explicitly handle in templates. And special cases are bad. What I want is for 'void' to behave like a normal type. This is not a crazy idea. 'void' can be considered as a unit type[0] in type theory. Basically, it is a type that can hold exactly 1 value (so you don't need any storage space to store it). And it exists in many programming languages. D actually already partially have 'void' as a unit type. For example: void a() { return a(); } // returning void in a void function Why don't we make it consistent across the whole language? Here is how 'void' would behave if we made it a unit type: void a; // fine pragma(msg, a.sizeof); // 0 void b = a; // fine writeln(a); // prints something intelligent about void struct A { void placeholder; // fine } pragma(msg, A.sizeof); // 1, same as empty struct [0]: https://en.wikipedia.org/wiki/Unit_type
Re: Is package.d a good idea?
On Sunday, 1 July 2018 at 18:03:41 UTC, Adam D. Ruppe wrote: On Sunday, 1 July 2018 at 14:23:36 UTC, Yuxuan Shui wrote: I was suggesting we do what Rust did. i.e. 'import foo', imports foo.d, which can in turn do 'import foo.bar', which will import foo/bar.d. Yeah, that's the way it should have been done in the first place. Nowhere else in D does it require a specific filename except package.d - it is a pointless inconsistency anyway. Now we just need to wait for someone to write the DIP
Re: Is package.d a good idea?
On Sunday, 1 July 2018 at 11:55:17 UTC, Jonathan M Davis wrote: On Sunday, July 01, 2018 11:36:51 Yuxuan Shui via Digitalmars-d wrote: [...] The entire reason that package.d was added as a feature was so that modules could be split into packages without breaking code, and it's still valuable for that. [...] I was suggesting we do what Rust did. i.e. 'import foo', imports foo.d, which can in turn do 'import foo.bar', which will import foo/bar.d.
Is package.d a good idea?
In Rust, they have something call mod.rs, which is very similar to package.d. When you use a module 'foo' in Rust, it can either be 'foo.rs' or 'foo/mod.rs'. If 'foo' has sub-modules, it has to be 'foo/mod.rs'. Now in the Rust 2018 edition, they are getting rid of mod.rs. So when you import 'foo', rustc will always look for 'foo.rs', and if 'foo' has submodules, it can still reside in 'foo/submodule.rs'. This makes me think if package.d is a good idea, and if we should try to get rid of it as well.
Re: Why are we not using libbacktrace for backtrace?
On Thursday, 14 June 2018 at 17:26:50 UTC, Johannes Pfau wrote: Am Thu, 14 Jun 2018 01:19:30 + schrieb Yuxuan Shui: Just ran into a problem where program will crash during stack trace. Turns out not only does druntime not support compressed debug info, it cannot handle it at all. So I was thinking why don't we use a existing and proven library for this, instead of roll our own? GDC uses libbacktrace since 2013: https://github.com/D-Programming-GDC/ GDC/blob/master/libphobos/libdruntime/gcc/backtrace.d I think the main problem for DMD/LDC is that libbacktrace is not an installed library, it's only available while building GCC. libbacktrace is a standalone library: https://github.com/ianlancetaylor/libbacktrace GCC is using it.
Why are we not using libbacktrace for backtrace?
Just ran into a problem where program will crash during stack trace. Turns out not only does druntime not support compressed debug info, it cannot handle it at all. So I was thinking why don't we use a existing and proven library for this, instead of roll our own?
Re: What's happening with the `in` storage class
On Saturday, 9 June 2018 at 07:56:08 UTC, Jonathan M Davis wrote: Now that it is defined with DIP 1000, it seems like pretty much everyone trying to use it has a hard time understanding it at first (at least beyond the really simple cases). It might have been because that the DIP is written in a somewhat confusing way. - Jonathan M Davis
Re: DIP Draft Review News
On Monday, 4 June 2018 at 11:28:26 UTC, rikki cattermole wrote: Thought: Couldn't we have alternative names in the parameter instead? E.g. ```D void foo(int x/x0/width, int y/y0/height){} ``` This intuitively means that any combination of the parameter names would work (e.g. (x, y0), (width, y)), which is not what we want.
Re: DIP Draft Review News
On Monday, 4 June 2018 at 10:30:18 UTC, rikki cattermole wrote: On 04/06/2018 10:05 PM, Yuxuan Shui wrote: On Monday, 4 June 2018 at 05:46:04 UTC, rikki cattermole wrote: [...] Not sure what you meant? This definitely does not error out: https://godbolt.org/g/PAiFPw ```D @named: int add(int a, int b); int add(int b, int a) { assert(a > 0); return a + b; } void main() { add(2, 0); } ``` This shouldn't fail to compile. I think it's made clear in the DIP, parameter names play no role in overload resolution. [...] Care to elaborate why? In this DIP, name prefix on caller side is optional, caller is allowed to leave out any number of argument names if they want. Not all parameters should be used as named arguments. Two syntax's one purpose isn't desired, which the DIP currently encourages. Why is this two syntaxes one purpose? Personally I want to keep named and unnamed completely separate and focus more upon public API. While I'm not keen on 2 and definitely would love for 3, my first point is what will determine if I vote yes or not (assuming it gets there). My instincts are saying that it simply hasn't been thought through enough just yet and that there will be some real trouble with it. I've dwelt on this for a couple of months now, and keeping thinking on it myself is not going to help. That's why I'm asking for feedback. Ambiguity is nobody's friend when it comes to programming language proposals. You have time to think it over, and I could be very wrong (of course); but other wise as a lite version of named arguments its not a bad DIP, just maybe we can do better for D ;)
Re: DIP Draft Review News
On Monday, 4 June 2018 at 05:46:04 UTC, rikki cattermole wrote: On 04/06/2018 5:01 PM, Mike Parker wrote: Named arguments lite I'm concerned about this DIP (keep in mind I wrote a referenced WIP DIP). 1. Reordering of parameters that match (with overloads) ```D int add(int a, int b); int add(int b, int a) { ... } ``` This part of the DIP needs quite a bit of filling out and I expect to have a lot of corner cases. Are you saying that you have an add that is extern'd or do you mean a named argument function overload? By conventional wisdom it definitely should error out. Not sure what you meant? This definitely does not error out: https://godbolt.org/g/PAiFPw 2. All or nothing. ```D int add(int x, int y); @named: int add(int b, int a) { ... } ``` This is one of the reasons some people /don't/ want named arguments and have said that they out right would not use a language with it. Care to elaborate why? In this DIP, name prefix on caller side is optional, caller is allowed to leave out any number of argument names if they want.
Re: Clash When Using Function as Template Value-Parameters?
On Tuesday, 29 May 2018 at 12:37:04 UTC, Vijay Nayar wrote: On Tuesday, 29 May 2018 at 11:36:11 UTC, Yuxuan Shui wrote: No, wait a second. (a)=>a is in default argument list, so it is in the global scope. And it was instantiated when you instantiate BTree with char. Could you explain that part a bit for me? Yes, (a) => a is a default value, but when you say it is in the global scope, are you saying that a single object "(a) => a" is created in the global scope and not created for each template argument list, e.g. "BTree!int" and "BTree!char"? I actually do not know in what scope such objects would be created, I had assumed it was per template-parameter list, but are you saying this is not the case? I believe that is the case. Normally that will be fine, because you can't modify them. Type-deduced lambda is a very special case, as in their parameter types are deduced on first use, so in a sense, they are "modified" by the first instantiation. BTW, I can't find the documentation about defining lambda with their parameter types omitted anywhere.
Re: Clash When Using Function as Template Value-Parameters?
On Tuesday, 29 May 2018 at 11:34:03 UTC, Yuxuan Shui wrote: On Saturday, 26 May 2018 at 11:56:30 UTC, Vijay Nayar wrote: I've been experimenting with code that uses std.functional : binaryFun and unaryFun, but I have found that using these methods makes it impossible to add function attributes like @safe, @nogc, pure, and nothrow, because no guarantee can be made about the functions created via a stream. For example, if you expect a comparator function like "a == b", someone can pass in "a.data--" instead. [...] This is probably a bug. BTree!char.lambda is clearly not the same as BTree!int.lambda, but the compiler seems to disagree? No, wait a second. (a)=>a is in default argument list, so it is in the global scope. And it was instantiated when you instantiate BTree with char.
Re: Clash When Using Function as Template Value-Parameters?
On Saturday, 26 May 2018 at 11:56:30 UTC, Vijay Nayar wrote: I've been experimenting with code that uses std.functional : binaryFun and unaryFun, but I have found that using these methods makes it impossible to add function attributes like @safe, @nogc, pure, and nothrow, because no guarantee can be made about the functions created via a stream. For example, if you expect a comparator function like "a == b", someone can pass in "a.data--" instead. [...] This is probably a bug. BTree!char.lambda is clearly not the same as BTree!int.lambda, but the compiler seems to disagree?
Re: Error about constructor calls in loops/labels, but there are no loops and labels?
I've been using Swift in the past few years quite a bit, and it always amuses me when it can't figure out some kind of inference that seems trivial, but it just gives up because the compiler takes too long to determine: "This [one line] statement is too difficult, please split into multiple statements." This is the kind of stuff you would be encountering. Clarification to my last point. I'm saying Swift's compiler is not smart enough, because other type inference languages doesn't seem to have this weird limitation. Worst case is they can't infer the type, then they fail back to not inferring, which is not worse than not having type inference. -Steve
Re: Error about constructor calls in loops/labels, but there are no loops and labels?
My response below might be a little off-topic. On Monday, 21 May 2018 at 13:06:14 UTC, Steven Schveighoffer wrote: [snip] There is something to be said for keeping the compiler dumb: 1. Dumb is easy to implement, explain, and understand -- if you set the bar low then more compilers will be able to handle the use cases. Having code that compiles with all available compilers is better than something that you need a specific "really smart" compiler to work. This would have been a fair point if there is more than one working D frontend right now. Maybe you are arguing the bar of D could be lower? Then the problem of where to draw the line pops up again. "Being dumb" couldn't be a goal of the language, right? 2. No matter how smart you make the compiler, you will get into situations that it can't figure out (halting problem). True. If you are going to have some situations that it doesn't handle, then it's really just a matter of where to draw the line. D has this problem with forward references -- it's a never ending battle of shuffling things around sometimes. The smarter you get, the more odd and difficult to deal with the cases that won't work become. I would argue this is not because the compiler is too smart. This is because the behavior of the compiler is not pinned down. How D resolve forward references is not well documented, so when problem occurs you have to guess (or read the compiler source code, like a real man) to figure out how to solve it. With inner functions, it's really easy to satisfy the compiler here. You just have to make a few changes in your code, I don't see it being a huge problem. Not a huge problem, but certainly a rough edge that might make someone think D is an unrefined language. I've been using Swift in the past few years quite a bit, and it always amuses me when it can't figure out some kind of inference that seems trivial, but it just gives up because the compiler takes too long to determine: "This [one line] statement is too difficult, please split into multiple statements." This is the kind of stuff you would be encountering. Not sure if this is another case of compiler being not smart enough? And the solution seems to be pretty simple here. -Steve
Re: Error about constructor calls in loops/labels, but there are no loops and labels?
On Sunday, 20 May 2018 at 14:39:28 UTC, Jonathan M Davis wrote: Well, constructors are one of the few places that the compiler attempts flow analysis for stuff other than optimization, because it pretty much has to in order to do what the language needs. And no, it's not very sophisticated about it, because it's simpler to guarantee correctness that way. It also highlights why Walter is usually against doing much in the way of flow analysis. By designing the language such that it doesn't need much flow analysis, you mostly avoid problems like this. Unfortunately, it becomes more or less impossible to completely avoid it in constructors when you have const or immutable members, so the compiler does have to do some flow analysis in constructors. And it seems that Walter's solution in this sort of situation is to err on the side of having the compiler be stupid in order to avoid better guarantee correctness. Not being a compiler expert, I can't really comment on what the best approach would be here, but I know that Walter is typically against flow analysis at the semantic pass level precisely because it's very hard to get right, and it's always a battle between having it be sophisticated enough to not get in the programmers way and having it actually be guaranteed to be correct. As I understand it, flow analysis in stuff like the optimizer is _much_ easier, because the constructs you're dealing with are much easier. That's also why Walter and Andrei really like to design advanced language features in terms of lowering into simpler features (e.g. the use of destructors and scope statments all get lowered to try-catch-finally blocks). It's much easier to guarantee correctness with simpler features. As for this particular case, I expect that the best course of action is to report it in bugzilla and see what Walter thinks is the best approach. I can comment on Walter's basic approach and reasoning based on what he's said about these issues in the past, but I can't way what his response would be to this particular example. - Jonathan M Davis I would argue that the best approach is to design the language to avoid flow analysis as much as possible. But for places that need it, the compiler should do as best as it can.
Re: Error about constructor calls in loops/labels, but there are no loops and labels?
On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote: because it tends to become very difficult to get right in all cases and results in situations where the programmer is forced to do something in order to make the compiler shut up Well, doesn't this post show exactly this problem, and that's because the compiler is too dumb? Making the compiler smarter will only decrease the number of these cases.
Re: Error about constructor calls in loops/labels, but there are no loops and labels?
On Thursday, 17 May 2018 at 20:32:23 UTC, Steven Schveighoffer wrote: On 5/17/18 4:25 PM, DarkHole wrote: On Thursday, 17 May 2018 at 20:02:19 UTC, Steven Schveighoffer wrote: On 5/17/18 3:55 PM, DarkHole wrote: This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels. Switch cases are labels. But why? You mean why is it an error? Probably because the compiler needs to guarantee you are calling the super constructor, and it can't figure out the flow when it sees labels/loops. Not that it's always impossible, but it's likely a complication the compiler devs don't want to deal with. -Steve Why isn't the compiler doing proper flow analysis? Is it that just no one bothered to implement it?
Re: Extend the call site default argument expansion mechanism?
On Tuesday, 15 May 2018 at 13:59:37 UTC, jmh530 wrote: On Tuesday, 15 May 2018 at 13:16:21 UTC, Steven Schveighoffer wrote: [snip] Hm... neat idea. Somehow, opDispatch can probably be used to make this work even more generically (untested): struct WithAlloc(alias alloc) { auto opDispatch(string s, Args...)(auto ref Args args) if (__traits(compiles, mixin(s ~ "(args, alloc)"))) { mixin("return " ~ s ~ "(args, alloc);"); } } -Steve Example: https://run.dlang.io/is/RV2xIH Sadly with(WithAlloc!alloc) doesn't work. (If you have to use withAlloc.func everywhere, it kind of destroy the point, doesn't it?)
Re: Extend the call site default argument expansion mechanism?
On Friday, 11 May 2018 at 18:55:03 UTC, Meta wrote: On Friday, 11 May 2018 at 15:03:41 UTC, Uknown wrote: [...] It's not as pretty, and I don't know if it works outside this toy example yet, but you can do: import std.stdio; struct Allocator { auto call(alias F, Args...)(Args args) { return F(this, args); } void deallocateAll() { writeln("deallocateAll"); } } void f1(Allocator a, int n) { writeln("f1"); } void f2(Allocator, string s, double d) { writeln("f2"); } void main() { with (Allocator()) { scope(exit) deallocateAll; call!f1(2); call!f2("asdf", 1.0); } } I found another alternative to this: https://godbolt.org/g/3Etims
Re: Extend the call site default argument expansion mechanism?
On Thursday, 10 May 2018 at 15:15:03 UTC, Paul Backus wrote: On Thursday, 10 May 2018 at 14:37:00 UTC, rikki cattermole wrote: On 11/05/2018 2:33 AM, Yuxuan Shui wrote: On Thursday, 10 May 2018 at 14:28:39 UTC, JN wrote: But doing it with default argument expansion saves you 1 allocation, has 1 less type, while being just as readable. I think that's a win. class -> struct, now it is back to 1 allocation. Even easier: alias createDataStructure = (...) => new DataStructure(..., alloc); I think one problem with this and Factory, is that you have to create one alias/lambda/factory type for every type that takes an allocator.
Re: Extend the call site default argument expansion mechanism?
On Thursday, 10 May 2018 at 14:30:49 UTC, Seb wrote: On Thursday, 10 May 2018 at 14:15:18 UTC, Yuxuan Shui wrote: So in D I can use default argument like this: int f(int line=__LINE__) {} [...] Why not define a TLS or global variable like theAllocator? Or if you know it at compile-time as an alias? Because my proposal is better encapsulated. Definitions of expanded default arguments are scoped, so in the given example, you can have different __ALLOC__ in different scope, where different allocators might be needed. My proposal is basically an alias, but an alias which is recognized by compiler as subtitution keywords for default arguments (like __LINE__, __FILE__).
Re: Extend the call site default argument expansion mechanism?
On Thursday, 10 May 2018 at 14:28:39 UTC, JN wrote: On Thursday, 10 May 2018 at 14:15:18 UTC, Yuxuan Shui wrote: [...] For things like this you can use the OOP Factory pattern, pseudocode: class DataStructureFactory { this(Allocator alloc) { this.alloc = alloc; } Allocator alloc; DataStructure createDataStructure(...) { return new DataStructure(..., alloc) } } DataStructureFactory factory = new DataStructureFactory(new SomeAllocator()) auto data1 = factory.createDataStructure(...) auto data2 = factory.createDataStructure(...) auto data3 = factory.createDataStructure(...) But doing it with default argument expansion saves you 1 allocation, has 1 less type, while being just as readable. I think that's a win.
Re: Extend the call site default argument expansion mechanism?
On Thursday, 10 May 2018 at 14:17:50 UTC, rikki cattermole wrote: On 11/05/2018 2:15 AM, Yuxuan Shui wrote: [...] Bad idea, too much magic. This magic is already there in D. I just want to use it in a different way.
Extend the call site default argument expansion mechanism?
So in D I can use default argument like this: int f(int line=__LINE__) {} And because default argument is expanded at call site, f() will be called with the line number of the call site. This is a really clever feature, and I think a similar feature can be useful in other ways. Say I need to construct a bunch of data structure that takes an Allocator argument, I need to do this: ... auto alloc = new SomeAllocator(); auto data1 = new DataStructure(..., alloc); auto data2 = new DataStructure(..., alloc); auto data3 = new DataStructure(..., alloc); ... This looks redundant. But if we have the ability to define more special keywords like __LINE__, we can do something like this: ... // constructor of DataStructure this(Allocator alloc=__ALLOC__) {...} ... auto alloc = new SomeAllocator(); define __ALLOC__ = alloc; // And we don't need to pass alloc everytime ... Is this a good idea?
Re: partially mutable immutable type problem, crazy idea
On Wednesday, 9 May 2018 at 00:58:51 UTC, jmh530 wrote: On Tuesday, 8 May 2018 at 22:31:10 UTC, Yuxuan Shui wrote: snip] This doesn't compile for me on run.dlang.io: onlineapp.d(22): Error: template onlineapp.f cannot deduce function from argument types !()(B), candidates are: onlineapp.d(1):onlineapp.f(T)(immutable T a) Not supposed to. Was proposing an (crazy) idea here.
Re: partially mutable immutable type problem, crazy idea
After watching the DConf 2018 video, I came up with this wild idea: auto f(T)(immutable T a) { // If T is a aggregate type, and I only use (directly // or indirectly) the immutable fields of T, // Then it should be OK to call f() with a partially mutable type return a.x+1; } void main() { struct A { int x; } A a; immutable(A) b; f(a); // <- not fine f(b); // <- fine class B { immutable int x = 10; double f; } auto c = new B; f(c); // <- fine too } I think this should solve the reference counting an immutable object, no? To f(), T will just looks like a normal immutable, uncopyable (because copying means modifying the reference counter) type
Re: Unreachable warning is annoying
On Tuesday, 13 March 2018 at 14:40:21 UTC, Steven Schveighoffer wrote: On 3/13/18 10:25 AM, Yuxuan Shui wrote: [...] This has been discussed before. There are a few ways around this. One is to do what you did. Another is to append a sentinel, or use id to terminate the loop: foreach(id, R; S) { static if(is(T == R)) return id; else static if(id + 1 == S.length) return -1; } Wait, I don't understand how this works. Isn't this going to be expanded to something like: return 0; return 4; // One return for every match ... return -1; Shouldn't this trigger unreachable warning too? IMO, the "unreachable statement" error is bogus because it's reachable depending on the template parameters! In the coder's eyes, what matters is whether the line of source is reachable or not, not whether it's reachable in that instantiation. Agreed. -Steve
Unreachable warning is annoying
See this simple example: int staticFind(T, S...)() { foreach(id, R; S) { if (is(T == R)) return id; } } return -1; } staticFind!(int, int, double) will generate a 'statement is unreachable' warning, and staticFind!(int, double) won't. This behaviour is understandable, but annoying. If template writer cares about this unreachable warning, they basically can't use any early return at all. So previous example has to be re-written into: int staticFind(T, S...)() { int ret = -1; foreach(id, R; S) { if (is(T == R) && ret == -1) ret = id; } } return ret; } However, this might not always be so simple in more complex functions. And this could potentially increase compilation time (maybe?).
Re: How to stringify a template instantiation expression?
On Thursday, 1 March 2018 at 17:48:02 UTC, Simen Kjærås wrote: On Thursday, 1 March 2018 at 16:46:30 UTC, Yuxuan Shui wrote: [...] string TemplateStringOf(T...)() if (T.length == 1) { import std.traits : TemplateOf, TemplateArgsOf; import std.meta : AliasSeq, staticMap; import std.string : indexOf; import std.conv : text; static if (is(typeof({ alias a = TemplateOf!T; }))) { alias Tmp = TemplateOf!T; alias Args = TemplateArgsOf!T; [...] Ah, thanks. I was trying to match template instantiation using is() (i.e. is(T == S!R, S, R...)). But this doesn't work if T is a template. Reading the code of TemplateOf, I realized I have to use template constraints for that. Maybe we can add support for something like is(alias T == ...)?
Re: How to stringify a template instantiation expression?
On Thursday, 1 March 2018 at 16:46:30 UTC, Yuxuan Shui wrote: On Wednesday, 28 February 2018 at 15:49:25 UTC, aliak wrote: On Wednesday, 28 February 2018 at 15:09:56 UTC, Yuxuan Shui wrote: For a template instantiation expression like A!(B, C!(D, E)), I want to get a string "A!(B, C!(D, E))", better if A, B, C, D, E is replaced by fully qualified name. Is this possible? A!(B, C!(D, E)).stringof I guess. Will print the former. There's a Learn forum as well btw :) Cheers Did you actually try that? With dmd 2.079-rc1, this: template A(T...) {} struct B {} struct D {} struct E {} template C(T...) {} pragma(msg, (A!(B, C!(D, E))).stringof); Prints: A!(B, __T1CTS2ax1DTSQh1EZ) When compiled Even worse, if the template instantiation yields another template, e.g: template A(T) { template A(T) {} } A!int.stringof returns "A(T)", which is not useful at all.
Re: How to stringify a template instantiation expression?
On Wednesday, 28 February 2018 at 15:49:25 UTC, aliak wrote: On Wednesday, 28 February 2018 at 15:09:56 UTC, Yuxuan Shui wrote: For a template instantiation expression like A!(B, C!(D, E)), I want to get a string "A!(B, C!(D, E))", better if A, B, C, D, E is replaced by fully qualified name. Is this possible? A!(B, C!(D, E)).stringof I guess. Will print the former. There's a Learn forum as well btw :) Cheers Did you actually try that? With dmd 2.079-rc1, this: template A(T...) {} struct B {} struct D {} struct E {} template C(T...) {} pragma(msg, (A!(B, C!(D, E))).stringof); Prints: A!(B, __T1CTS2ax1DTSQh1EZ) When compiled
How to stringify a template instantiation expression?
For a template instantiation expression like A!(B, C!(D, E)), I want to get a string "A!(B, C!(D, E))", better if A, B, C, D, E is replaced by fully qualified name. Is this possible?
Re: What does rt/sections_elf_shared.d do? (Porting dmd to musl)
On Sunday, 17 December 2017 at 12:45:58 UTC, Yuxuan Shui wrote: However, going through sections_elf_shared.d, it makes me feel it's doing some magic tricks with dl functions, but I don't know what for? Looks like it's also repeating some work that is already done by the dynamic linker...
What does rt/sections_elf_shared.d do? (Porting dmd to musl)
I'm trying to get dmd and phobos working with musl. Right now I have a bootstrapped compiler built with musl, which seems to work fine. However user applications will segmentation fault before even reaches main. I investigated a bit. Looks like musl is not happy with how druntime uses dlopen related functions. When a D library loads, it tries to call _d_dso_registry, which will try to get a handle of the library using dlopen. Meaning dlopen will be called on the library itself while it's still loading. This seems to break musl. Although this might also be a bug on musl side: it tries to call init functions even when RTLD_NOLOAD is passed to dlopen. However, going through sections_elf_shared.d, it makes me feel it's doing some magic tricks with dl functions, but I don't know what for? If my understand is correct, it's used to register TLS storage to GC. If that's the case, there must be simpler ways to do that.
Re: Supporting musl libc
On Tuesday, 17 May 2016 at 08:51:01 UTC, Jacob Carlborg wrote: As an alternative to glibc there's a C standard library called musl [1]. This is the C standard library used by ELLCC [2], a cross-compiler based on Clang. This cross-compiler makes it very easy to target other platforms and can be used as the C compiler when building with LDC. The issue is that musl doesn't support the functions defined by execinfo.h: backtrace, backtrace_symbols_fd and backtrace_symbols, since these are glibc extensions. As far as I can see, these functions are used in two places in druntime: src/rt/backtrace/dwarf.d [3] and src/core/runtime.d [4]. The imports of execinfo is guarded by version(CRuntime_Glibc). I see that CRuntime_Glibc is a predefined version identifier defined by the compiler on Linux. I'm not sure how to best handle different C standard libraries when it comes to choosing which one to use. Is it best to choose that when building the compiler or when building druntime? Or can it be a runtime option? [1] https://www.musl-libc.org [2] http://ellcc.org [3] https://github.com/dlang/druntime/blob/master/src/rt/backtrace/dwarf.d#L41 [4] https://github.com/dlang/druntime/blob/master/src/core/runtime.d#L433-L434 I tried to build dmd on musl, and it seems to work relatively well. I need to build dmd 2.067 for bootstrapping. It doesn't build out-of-box, but there's patches floating around. There're some missing symbols in druntime: a couple math related, backtrace() and backtrace_symbols(). The former ones can be workaround, but and proper solution is needed. The latter ones can be solved by linking in libbacktrace().
Re: Proposal: Support for objects in switch statements
On Wednesday, 1 November 2017 at 01:16:32 UTC, solidstate1991 wrote: After I started to alter my graphics engine to use the multiple kinds of bitmaps (now using multiple language features, like templates and aliases) on one layer, I noticed that type detection of bitmap objects would be easier and better readable, if instead of: if(bitmapObject.classinfo == typeof(Bitmap4Bit)){ ... }else if(bitmapObject.classinfo == typeof(Bitmap8Bit)){... I could easily use this: switch(bitmapObject.classinfo){ case typeof(Bitmap4Bit): ... case typeof(Bitmap8Bit): } On the other hand I cannot really think other uses for such language feature, maybe with structs. Maybe use something similar to recieve()? Like: match(obj, (Type1 x) => {}, (Type2 x) => {}, ...)
Re: -betterC and extern(C++) classes
On Sunday, 10 September 2017 at 14:42:42 UTC, Moritz Maxeiner wrote: On Sunday, 10 September 2017 at 14:04:20 UTC, rikki cattermole wrote: On 10/09/2017 2:19 PM, Moritz Maxeiner wrote: If TypeInfo for extern(C++) classes is removed, couldn't final extern(C++) classes without base class and which don't implement any interfaces omit the vtable so that the following assert holds: --- final extern(C++) class Foo {} static assert (__traits(classInstanceSize, Foo) == 0LU); --- The reason I ask is that fairly often I have an abstraction that's better suited as a reference type than a value type, but doesn't need any runtime polymorphy (or the monitor standard classes have). Structs + pointers are the only way I know of to avoid the (in this special case) unneeded vtable overhead, but it always ends up looking worse to read. We can do it for any class if its final. Even final classes can always inherit (potentially already overridden) virtual methods from their parent classes and since all normal D classes inherit from core.object : Object [1], which defines virtual methods (`toString`, `toHash`, `opCmp, and `opEquals`), I don't see how this can be true. With a final class reference, we always know what function to call at compile time (since it can't be inherited). Therefore we don't need a vtable. The problem isn't generating the vtable's. But the information required for casting. This applies to normal D classes, but D doesn't support (dynamic) casts for extern(C++) classes, anyway, so this shouldn't be an issue for them. [1] https://github.com/somzzz/druntime/blob/74882c8a48dd8a827181e3b89c4f0f205c881ac5/src/object.d#L50
Re: -betterC and extern(C++) classes
By the way, can we dynamic_cast extern(C++) classes in C++? If not, what are we generating these TypeInfo_Class for?
Re: -betterC and extern(C++) classes
On Sunday, 10 September 2017 at 09:31:55 UTC, Walter Bright wrote: On 9/10/2017 1:40 AM, Yuxuan Shui wrote: I was experimenting with -betterC and found out that C++ classes doesn't work. Because the resulting object file needs a symbol "_D14TypeInfo_Class6__vtblZ" which is in druntime. I suppose this is to support T.classinfo? Could we remove T.classinfo and make classes work under -betterC? Or is there some other reason preventing this from happening? Yes, we do want to move towards "Better C++" working in an analogous manner, and that means removing the typeinfo dependency. Is there a plan? Are there any simple tasks I can take/help?
-betterC and extern(C++) classes
I was experimenting with -betterC and found out that C++ classes doesn't work. Because the resulting object file needs a symbol "_D14TypeInfo_Class6__vtblZ" which is in druntime. I suppose this is to support T.classinfo? Could we remove T.classinfo and make classes work under -betterC? Or is there some other reason preventing this from happening? Thanks.
Re: Release D 2.076.0
On Friday, 1 September 2017 at 14:03:26 UTC, Martin Nowak wrote: Glad to announce D 2.076.0. This release comes with static foreach, many -betterC enhancements, various phobos additions, an -mcpu=avx2 switch, and lots of bugfixes. Thanks to everyone involved in this . http://dlang.org/download.html http://dlang.org/changelog/2.076.0.html - -Martin " -betterC enhancements " is listed twice in the changelog
Re: Dynamic array leak?
On Friday, 11 August 2017 at 18:44:56 UTC, bitwise wrote: struct S { static int count = 0; this(int x) { ++count; } this(this) { ++count; } ~this() { --count; } } int main(string[] argv) { S[] x = [S(1), S(1)]; writeln("GC allocated: ", (GC.addrOf(x.ptr) !is null)); x = null; GC.collect(); writeln("live objects: ", S.count); return 0; } output: GC allocated: true live objects: 2 expected: GC allocated: true live objects: 0 Is this a bug? I thought that the first writeln() may be leaving a copy of the pointer lingering on the stack somewhere, but the output is still "live objects: 2" with that line commented out. Thanks My guess is a pointer to the array still lives somewhere on the stack. This gives the expected output: void f() { S[] x = [S(1), S(1)]; writeln("GC allocated: ", (GC.addrOf(x.ptr) !is null)); x = null; } int main(string[] argv) { f(); GC.collect(); writeln("live objects: ", S.count); return 0; }
Re: [OT] Generative C++
On Tuesday, 1 August 2017 at 22:06:28 UTC, Walter Bright wrote: On 7/31/2017 5:41 AM, Joakim wrote: If he's right that C++ use is so balkanized, this will simplify some code but further balkanize the language. That might be worth it for them, but rather than simplifying the language, it makes it more powerful and more complex, heading higher up into the hills rather than the lower ground he claims to be heading for. I can't say I understand the proposal, but if it is similar to AST macros, my argument against that is well known and similar to yours. Can you give us a pointer to your arguments? Some of us (me) are not familiar with them. Thanks!
[OT] Generative C++
Someone made an interesting proposal to C++: https://herbsutter.files.wordpress.com/2017/07/p0707r1.pdf Thoughts?
Re: proposed @noreturn attribute
On Wednesday, 19 July 2017 at 10:35:37 UTC, Stefan Koch wrote: On Wednesday, 19 July 2017 at 10:24:35 UTC, Marc Schütz wrote: On Sunday, 16 July 2017 at 20:44:13 UTC, Andrei Alexandrescu wrote: Perhaps we go the inverse route and define the bottom type as typeof(*null). Would that simplify matters? There is some good consistency about it: null: a pointer to anything. But can't be dereferenced. *null: well, therefore... anything. But can't be created. That sounds more like a top type, though, because as you said it can be "anything". A bottom type can not be anything, but only nothing. It's the bottom. Bottom is to Types, as Object is to Classes. Actually, Object should be considered the Top type. All Classes are sub-classes of Object.
Re: proposed @noreturn attribute
On Tuesday, 18 July 2017 at 15:26:59 UTC, Timon Gehr wrote: On 18.07.2017 14:19, Stefan Koch wrote: [...] D has a C-inspired first-order type system, so it is not necessarily crucial to have it in D. (The reason I got involved in this thread is that it was proposed to add Bottom as a type that is not really a type; 'void' is annoying enough as the 'null' of types. We don't really need another one of those.) [...] What about void?
Re: Question on @nothrow
On Wednesday, 31 May 2017 at 09:31:48 UTC, Jonathan M Davis wrote: On Wednesday, May 31, 2017 08:18:07 Vasileios Anagnostopoulos via Digitalmars-d-learn wrote: [...] Well, if you're not doing checked exceptions, the interesting question is really what _doesn't_ throw rather than what throws, because if the compiler knows that a function doesn't throw, it can optimize out the exception handling mechanisms that are normally required. I don't think this is possible in current D? @nothrow functions can still throw Error.
Re: Question on @nothrow
On Wednesday, 31 May 2017 at 08:18:07 UTC, Vasileios Anagnostopoulos wrote: Hi, after reading various articles bout the "supposed" drawbacks of checked exceptions I started to have questions on @nothrow. Why there exists and not a @throws annotation enforced by the compiler? I understand that people are divided on checked exceptions and each side has some valid points. But explicitly marking a function as throwing "something" is another subject. Why have the dlang community reached to the decision to use @nothrow and not a @throws? Adding @throws to a function requires changing all the functions downstream. Adding @nothrow doesn't.
Re: C++17 cannot beat D surely
On Sunday, 4 June 2017 at 04:39:21 UTC, Adam D. Ruppe wrote: On Sunday, 4 June 2017 at 04:34:44 UTC, Mike Parker wrote: I would not have expected enum b = sort(a) to trigger an allocation. auto b, yes, of course (and the disassembly from that is not much different). So I'd love to see a blog post explaining it. I don't think I can do a full-on blog post, but I can answer it in a couple sentences: `enum` is treated by the compiler just like literals. Array literals allocate at each usage point, therefore enum arrays allocate at each usage point. (*each* usage point) I think the allocation is because sort returns a SortedRange, not an array. So even this allocates: enum b = a.sort; writeln(b[1]); OTOH, this doesn't allocate: enum b = a.sort.array; writeln(b[1]);
Re: How to move append to an array?
On Tuesday, 16 May 2017 at 01:34:50 UTC, Stanislav Blinov wrote: On Tuesday, 16 May 2017 at 01:22:49 UTC, Yuxuan Shui wrote: Can I expand an array with uninitialized object? Or can I rely on the compiler to optimize the initialization away? Built-in arrays always default-initialize their elements. If you need something that unsafe, there's std.array.uninitializedArray: http://dlang.org/phobos/std_array.html#uninitializedArray What are you trying to achieve? I just wish ~= could take moved objects.
Re: How to move append to an array?
On Monday, 15 May 2017 at 23:36:06 UTC, Stanislav Blinov wrote: On Monday, 15 May 2017 at 21:38:52 UTC, Yuxuan Shui wrote: Suppose I have a struct A { @disable this(this); } x; How do I append it into an array? Do I have to do array.length++; moveEmplace(x, array[$-1]); ? moveEmplace is for moving an initialized object into an uninitialized one. Use the two-argument move() function: move(x, array[$-1]); Can I expand an array with uninitialized object? Or can I rely on the compiler to optimize the initialization away?
How to move append to an array?
Suppose I have a struct A { @disable this(this); } x; How do I append it into an array? Do I have to do array.length++; moveEmplace(x, array[$-1]); ?
code.demangle can't demangle a type.
So in this document: http://yshui.gitlab.io/sdpc/sdpc/parsers/whitespace.html Part of the type name is still mangled. I found ddox use core.demangle.demangleType internally. So I guess code.demangle is following behind dmd? Is there a better way to demangle a name?
Re: weird empty string
On Saturday, 13 May 2017 at 00:59:14 UTC, Stanislav Blinov wrote: On Saturday, 13 May 2017 at 00:36:55 UTC, mogu wrote: ```d if (null) "1".writeln; if ("") "2".writeln; if ("" == null) "3".writeln; ``` Output: 2 3 How to understand this? Boolean conversion on an array works on array's pointer, not it's length. So even though `"".length == 0`, `"".ptr != null`, and so `cast(bool)"" == true`. However if ([]) "1".writeln; prints nothing. So why does "" has non-null pointer while [] has null pointer? Looks inconsistent.
Turn .opApply into ranges
I wondered if I can turn struct that defines opApply into ranges. And it turns out to be surprisingly easy: https://gist.github.com/yshui/716cfe987c89997760cabc2c951ca430 Maybe we can phase out opApply support in foreach? ;) BTW, is there a way to get the "element type" from .opApply?
Re: Working code in an upcoming PR by Timon Gehr
On Tuesday, 9 May 2017 at 13:19:09 UTC, Timon Gehr wrote: On 07.05.2017 19:03, Stanislav Blinov wrote: On Sunday, 7 May 2017 at 16:57:58 UTC, Andrei Alexandrescu wrote: [...] I see only unsurprising Jpeg artifacts and not much more :) It's too low resolution to make anything out. It's approximately this: --- alias Seq(T...)=T; void main(){ import std.stdio: writeln; import std.conv: to; static foreach(i;Seq!(0,1,2)){ mixin(`int x`~to!string(i)~" = i;"); } writeln(x0," ",x1," ",x2); } --- ./src/dmd -run staticforeach.d DMD v2.075.0-devel-fd4ff76 DEBUG 0 1 2 --- That was the first test case that worked. I have made it almost feature-complete yesterday: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d Yes! Finally!
Local pointer escape under current DIP1000 implementation
Code: @safe auto id(scope int *p) { int*[] a; a ~= p; return a; } @safe int *bar() { int i; return id()[0]; //pointer to local escaped } Compiles with -dip1000
Re: Function names and lambdas
On Thursday, 6 April 2017 at 18:45:26 UTC, Ali Çehreli wrote: On 04/06/2017 11:37 AM, Russel Winder via Digitalmars-d-learn wrote: [...] I think it's just a design choice. C implicitly converts the name of the function to a pointer to that function. D requires the explicit & operator: alias Func = int function(int); int foo(int i) { return i; } void main() { Func[] funcs = [ ]; } Close to what you mentioned, name of the function can be used as an alias template parameter: void bar(alias func)() { func(42); } int foo(int i) { return i; } void main() { bar!foo(); } Ali Main reason is probably UFCS.
Re: CTFE Status 2
On Wednesday, 5 April 2017 at 16:06:39 UTC, H. S. Teoh wrote: On Wed, Apr 05, 2017 at 11:20:28AM +, Yuxuan Shui via Digitalmars-d wrote: [...] Did you read the entire article? There is an entire section dedicated to interleaving of CTFE and templates. And no, you still cannot run CTFE on the same part of the AST that is being template-expanded. But you *can* run CTFE on a subtree that has already been fully expanded. And no, the forum post you linked to has nothing to do with CTFE. The so-called "static foreach" is unrolled at AST expansion time, and is not run through CTFE at all (unless later on you call the expanded function at "compile-time"). And is() expressions are also not CTFE, they are also evaluated at AST expansion time. Read the entire article first. ;-) T I was talking about the use of R.front, R.drop in the template.
Re: CTFE Status 2
On Sunday, 2 April 2017 at 04:34:34 UTC, H. S. Teoh wrote: On Sat, Apr 01, 2017 at 05:06:14PM +, Inquie via Digitalmars-d wrote: [...] How far off until newCTFE is usable to compile the majority of templates out there? CTFE and templates are two separate things. You may want to read this (draft) article to get a better understanding of how they fit together: https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time T CTFE and template expansion might be more tangled than you thought. For example, you do have access to CTFE during template expansion: http://forum.dlang.org/thread/yaekhryalyxyooaiu...@forum.dlang.org
Re: Of the use of unpredictableSeed
On Sunday, 26 March 2017 at 17:55:20 UTC, Nick Sabalausky (Abscissa) wrote: 2. Maybe the std.random docs need to be more clear, right up top, that it's not for anything security-related. Agreed. Like what Python did here: https://docs.python.org/3/library/random.html
Re: Comparing two AliasSeq
On Saturday, 25 March 2017 at 05:20:44 UTC, Jonathan M Davis wrote: On Saturday, March 25, 2017 04:57:26 Yuxuan Shui via Digitalmars-d-learn wrote: [...] An AliasSeq isn't really ever a type. AliasSeq!(int, float) is a list of types, not a type itself, and is expressions supports comparing those in at least some instances, because is expressions operate on types, and having them support a list of types is useful. Calling AliasSeq!(int, float) a type would be like claiming that the (int, float) in foo!(int, float) a type. It's a list - a list of template arguments in this case - but it's still a list and not itself a type. [...] Because I want to make use of the "static foreach unrolling" feature (I don't know what's the official name). [...]
Re: Comparing two AliasSeq
On Saturday, 25 March 2017 at 04:23:31 UTC, Jonathan M Davis wrote: On Saturday, March 25, 2017 03:25:27 Yuxuan Shui via Digitalmars-d-learn wrote: In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why? Well, is expressions normally compare types, not values, and AliasSeq!(0, 1, 2, 3, 4), isn't a type and doesn't contain types. static assert(is(AliasSeq!int == AliasSeq!int)); passes, whereas static assert(is(AliasSeq!0 == AliasSeq!0)); does not. So, I expect that the issue is that you're dealing with values rather than types. You're also using : instead of ==, and : _definitely_ is for types (since it checks for implicit conversion, not equality), so it wouldn't have entirely surprised me if == worked when : didn't, but == doesn't either. What you proobably should do is either convert the AliasSeq's to dynamic arrays or ranges - e.g. [AliasSeq!(0, 1, 2, 3, 4)] or only(AliasSeq!(0, 1, 2, 3, 4)) - though in both cases, that really only makes sense when you already have an AliasSeq, since [] and only will take the values directly. - Jonathan M Davis I see. I always thought tuple() is a type... So a tuple of types is a type, but a tuple of mixed types and values is not a type. Doesn't seem very consistent. Here is the solution I will go with: struct test(T...) { } import std.range; static assert (is(test!(expandRange!(iota(0,5))) == test!(0, 1, 2, 3, 4)));
Comparing two AliasSeq
In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why?
Re: Parameterized template value parameter
On Friday, 24 March 2017 at 20:43:18 UTC, Dmitry Olshansky wrote: On 3/24/17 12:24 AM, Yuxuan Shui wrote: So I was trying to make my template take a value parameter, whose type is also a parameter to the template. e.g.: template A(Char[] str, Char); But dmd complains about 'Char' being undefined. I have to write: template A(Char, Char[] str); Which is inconvenient, because now 'Char' can't be deduced by the compiler. Can we make the first case work? How about this? template A(alias str) if(is(typeof(str) : Char[], Char)){ alias Char = typeof(str[0]); // ... } Yes. This is what I ended up doing (https://github.com/yshui/sdpc/blob/master/sdpc/parsers.d#L45). One problem of this is that 'str' is not longer restricted to be a compile time value. Which is probably fine, but kind of makes me uncomfortable. In general it's sometimes possible to do the deduction w/o introducing more template arguments. --- Dmitry Olshansky
Re: sdpc - Simple/Stupid D parser combinator
On Friday, 24 March 2017 at 17:53:14 UTC, Basile B. wrote: On Thursday, 23 March 2017 at 22:55:10 UTC, Yuxuan Shui wrote: [...] Thanks for sharing this but your project is not visible! Gitlab is a bit confusing because by default repositories are private. Go to your project setting(should be https://gitlab.com/yshui/sdpc/edit): - set "Project Visibility" to "public". - set "Repository" to "everyone with access". Thanks for pointing this out! Obviously I only set "Visibility" to "public" and forgot the other settings...
Parameterized template value parameter
So I was trying to make my template take a value parameter, whose type is also a parameter to the template. e.g.: template A(Char[] str, Char); But dmd complains about 'Char' being undefined. I have to write: template A(Char, Char[] str); Which is inconvenient, because now 'Char' can't be deduced by the compiler. Can we make the first case work?
Re: sdpc - Simple/Stupid D parser combinator
BTW, ddox cleanly has some problem with this symbol: https://yshui.gitlab.io/sdpc/sdpc/parsers/skip_whitespace.html
sdpc - Simple/Stupid D parser combinator
GitLab: https://gitlab.com/yshui/sdpc Documents: https://yshui.gitlab.io/sdpc Dub: http://code.dlang.org/packages/sdpc I started this project ~1.8 years ago. It only took me a couple of weeks to write, and I learned a lot about D's template system (and its limitations) by writing it. But back then I wasn't confident with the code quality and documentation enough to make it public. Then life caught up with me and I can't spend time on it. Recently I finally got some time and decided to cleanup the code and make it available to more people. Now I'm comfortable with it enough to have more eyes on it. sdpc is a very simple parser combinator library. So it lacks some bells and whistles like left recursion or memoization. But it should be able to handle a lot of the simpler use cases. (I know we have pry now. A bit of competition won't hurt =] ).
template alias parameter vs type parameter.
Hi, Is there any difference, when a type is passed into an alias parameter vs into a type parameter?
Re: Annoying thing about auto ref function template
On Tuesday, 21 March 2017 at 01:10:38 UTC, Jonathan M Davis wrote: On Monday, March 20, 2017 22:14:37 Yuxuan Shui via Digitalmars-d wrote: On Monday, 20 March 2017 at 21:53:47 UTC, Jonathan M Davis wrote: > [...] Makes sense... OK, attempt 2: how about support implicit partial application for templates? Well, you can do something like template foo(T) { auto foo()(auto ref T t) { return t; } } void main() { alias f = foo!int; auto a = f(42); } and then foo!int, but you're not going to get a function pointer out of it, since for that, you need to instantiate the inner function template. It does give partial instantiation though. - Jonathan M Davis This is looks doable. Can we do this for all auto ref functions in phobos?
Re: Annoying thing about auto ref function template
On Monday, 20 March 2017 at 21:53:47 UTC, Jonathan M Davis wrote: On Monday, March 20, 2017 21:37:26 Yuxuan Shui via Digitalmars-d wrote: [...] auto ref for non-templates would not be quite the same thing, and regardless, it wouldn't help any with explictly instantiating a template that had an auto ref parameter. So, it really wouldn't solve the problem at all. It would just make it so that if you didn't want a templated function, you could use auto ref. [...] Makes sense... OK, attempt 2: how about support implicit partial application for templates? [...]
Re: Annoying thing about auto ref function template
On Monday, 20 March 2017 at 21:34:14 UTC, Yuxuan Shui wrote: On Monday, 20 March 2017 at 21:08:40 UTC, Jonathan M Davis wrote: [...] This is a bit tedious because it requires you creating a new function. Maybe we can create a template for that. But still, auto ref requires us to do things differently, which is annoying. Easy solution: just support auto ref for non-templates. I think someone has already did work on that?
Re: Annoying thing about auto ref function template
On Monday, 20 March 2017 at 21:08:40 UTC, Jonathan M Davis wrote: On Monday, March 20, 2017 13:20:52 Jonathan M Davis via Digitalmars-d wrote: So, yes, this particular restriction can be annoying, but there is a good reason for the restriction (though the error message _is_ pretty bad), and I have no idea how we would fix the problem. After thinking about this further, it does occur to me that there's a fairly simple workaround. e.g. auto foo(T)(T t) { return bar(t); } auto bar(T)(auto ref T t) { ... } Then you can just use foo!int. Now, that requires you to pick whether it's ref or not, but if there were a way to explicitly instantiate a function with an auto ref parameter, you'd have to do that anyway. - Jonathan M Davis This is a bit tedious because it requires you creating a new function. Maybe we can create a template for that. But still, auto ref requires us to do things differently, which is annoying.
Re: Annoying thing about auto ref function template
On Monday, 20 March 2017 at 19:49:03 UTC, Yuxuan Shui wrote: And you can't do that with an auto ref template, which makes them quite annoying. BTW, the error message you get when you try to do this, is not very helpful: 'auto' can only be used as part of 'auto ref' for template function parameters
Annoying thing about auto ref function template
An auto ref function template should behave like a normal function template, but it doesn't. You can fully instantiate a function template by specifying all of its template parameters, but you can't do that with auto ref templates. The only way to instantiate an auto ref template is to call it. This makes auto ref an outlier. Because you get a function by instantiate function template, you can pass the result as template alias argument, and you can create alias of the resulting function. And you can't do that with an auto ref template, which makes them quite annoying. I wonder why is auto ref designed this way? And can we change this?
We can't have alias of instantiated auto ref functions?
auto a(T)(auto ref T t) { return t; } void main() { alias tmp = a!int; import std.stdio; writeln(tmp(10)); } This gives this error message: test.d(1): Error: 'auto' can only be used as part of 'auto ref' for template function parameters Which is rather useless, and I have to dig into the code to find out why: the only way to instantiate a auto ref function is to call it. I think this is rather inconvenient.
Re: DConf 2017 Schedule
On Wednesday, 15 March 2017 at 22:07:26 UTC, Bastiaan Veelo wrote: On Wednesday, 15 March 2017 at 14:06:23 UTC, Yuxuan Shui wrote: So someone already wrote a parser combinator for D? I searched code.dlang.org (1.5 years ago?), and there was none, so I wasted couple weeks writing my own So, is yours on code.dlang.org? If it would have been, maybe Dmitry wouldn't have to waste his time. Anyway, Pegged definitely was there already. :-) It's called sdpc on code.dlang.org. its quality is probably not as high, and probably won't compile right now. Because I didn't have time to polish it. But I did create a toy language using it back then.
Re: DConf 2017 Schedule
On Tuesday, 14 March 2017 at 20:16:34 UTC, Ali Çehreli wrote: On 03/14/2017 09:35 AM, Moritz Maxeiner wrote: On Tuesday, 14 March 2017 at 16:12:56 UTC, Mike Parker wrote: Fresh from the D Foundation HQ, the DConf 2017 schedule [1] is now available for your perusal. If you haven't registered yet, you have just over five weeks to get it done. The registration deadline has been set for April 23, so don't procrastinate. Even better, head over to the registration page [2] and do it now! [1] http://dconf.org/2017/schedule/ [2] http://dconf.org/2017/registration.html Thanks, looks like lots of interesting talks! One thing though: Day 3: Saturday May 6, 2017 Day 4: Saturday May 7, 2017 Thanks. Apparently, that one's fixed. Everybody, you can make pull requests to https://github.com/dlang/dconf.org Don't use my clone of the repo as it involves an extra step. Ali So someone already wrote a parser combinator for D? I searched code.dlang.org (1.5 years ago?), and there was none, so I wasted couple weeks writing my own