Re: isExpression with bool template parameter
On Tuesday, 26 March 2013 at 06:15:54 UTC, cal wrote: static if (is(S!(int, 5) _ : S!(U), U...)) // line B, fail pragma(msg, U.stringof); // tuple(int, 5); oops the '// line B, fail' should not be there
Re: isExpression with bool template parameter
On Tuesday, 26 March 2013 at 06:03:55 UTC, cal wrote: I.e., why I can't match on some generic second parameter - what if the second parameter was an int: struct S(A, int B) {} static assert(is(S!(int, 5627) _ == S!(U, ??), U, ??)); how to match that in the isExpression? cheers, cal However this does work (and solves my problem): struct S(A, int B){} static if (is(S!(int, 5) _ : S!(U), U...)) // line B, fail pragma(msg, U.stringof); // tuple(int, 5); But it seems like is(S!(int, 5) _ : S!(U, V), U, V) should work to me.
Re: isExpression with bool template parameter
On Tuesday, 26 March 2013 at 05:28:22 UTC, Ali Çehreli wrote: I am not sure that I understand but usually the test is done in a context like foo() below: struct S(A, bool B) {} void foo(T)() { static assert(is(T == S!(U, false), U)); } void main() { foo!(S!(int, false))(); } Ali Maybe I gave a bad example, I guess I wonder why line A passes but line B fails: struct S(A, bool B) {} static assert(is(S!(int, false) _ == S!(U, false), U)); // line A, pass static assert(is(S!(int, false) _ == S!(U, V), U, V)); // line B, fail void main(){} I.e., why I can't match on some generic second parameter - what if the second parameter was an int: struct S(A, int B) {} static assert(is(S!(int, 5627) _ == S!(U, ??), U, ??)); how to match that in the isExpression? cheers, cal
fullyQualifiedName doesn't work with SortedRange
why doesn't this compile? import std.traits; import std.algorithm; void main(){ auto a=sort([1]); enum t=fullyQualifiedName!(typeof(a)); pragma(msg,t); } CT error: std/traits.d(298): Error: forward reference of variable parentPrefix Timothee Cour
Re: Possible bug
On Tue, 26 Mar 2013 01:28:03 -0400, Sergei Nosov wrote: Thank you, guys! You made the matters clear to me! It would be an interesting enhancement over C++. Although, Steven, I didn't quite understand what you're suggesting to use in case of "templated-struct-templated-constructor" Explicitly specifying struct parameters is ok. Deducing constructor parameters from arguments is also ok. But what if not all of the constructor parameters may be deduced? E.g. one of them is an int? Would it be a no-no case? or should we merge the lists in one? or should we use two bangs? S!(int, 4)!(byte, 5)(3) ? =) What you have to do is instantiate the template, then call the constructor: S!(int, 4).S!(byte, 5)(3) Note that the way templates work in D, a templated struct is really a shortcut for: template S(T) { struct S { ... } } So when you instantiate it, S!(int)(5) is really shorthand for S!(int).S(5). Every template is this way. The shorthand version calls on the "eponymous" member implicitly, that is, the member with the same name as the template. Currently, this only works if there is exactly one member. For example, a function template is really: template foo(T) { void foo(T t) {...} } So doing: foo!(int)(1) is really the same as: foo!(int).foo(1) It's all outlined here: http://dlang.org/template.html search for Implicit Template Properties -Steve
Re: isExpression with bool template parameter
On 03/25/2013 04:57 PM, cal wrote: Trying to figure out how to pattern-match struct S below with an isExpression: struct S(A, bool B) {} static assert ( !is(S!(int, false) _ == S!(U, bool), U) ); static assert ( !is(S!(int, false) _ == S!(U, V), U, V) ); static assert ( !is(S!(int, false) _ == S!(U, V), U, V : bool) ); void main(){} Can someone help? I am not sure that I understand but usually the test is done in a context like foo() below: struct S(A, bool B) {} void foo(T)() { static assert(is(T == S!(U, false), U)); } void main() { foo!(S!(int, false))(); } Ali
Re: Possible bug
Thank you, guys! You made the matters clear to me! It would be an interesting enhancement over C++. Although, Steven, I didn't quite understand what you're suggesting to use in case of "templated-struct-templated-constructor" Explicitly specifying struct parameters is ok. Deducing constructor parameters from arguments is also ok. But what if not all of the constructor parameters may be deduced? E.g. one of them is an int? Would it be a no-no case? or should we merge the lists in one? or should we use two bangs? S!(int, 4)!(byte, 5)(3) ? =)
Re: Question about auto ref
You make me curious about this new attribute. Maybe I could then help to implement this along with its task. I do not think anyone else has the time to do it. I hope that you will find the link.
Re: Question about auto ref
On Tuesday, March 26, 2013 00:52:56 Namespace wrote: > Forgot to ask: > Wouldn't it be better to publish this decision? > Many still believe the nonsense (like me) that 'auto ref' is > still the solution. An official decision would mean that Walter had been involved in it, and that hasn't happened. IIRC, Andrei said something positive about the temporary approach when it was brought up, but AFAIK, no official decision has been made. It's just that it became clear when discussing it that if we wanted to go with the temporary trick (which looks like the best solution), it really should apply to both templated and non-templated functions and that auto ref needs to retain its current meaning for templated functions, which then means that we need a new attribute. I suppose that we could always create a DIP for it though. - Jonathan M Davis
Re: Question about auto ref
Forgot to ask: Wouldn't it be better to publish this decision? Many still believe the nonsense (like me) that 'auto ref' is still the solution.
Re: Possible bug
On Mon, 25 Mar 2013 17:13:58 -0400, Ali Çehreli wrote: On 03/25/2013 12:40 PM, Steven Schveighoffer wrote: > On Mon, 25 Mar 2013 11:31:17 -0400, Ali Çehreli wrote: > >> This design allows templated constructors: >> >> struct S // <-- not a template >> { >> this(T)(T t) // <-- template >> { >> // ... >> } >> >> // ... >> } >> >> The same in C++... > > Templated constructors would not be disallowed if you allowed IFTI on > templated structs/classes without templated constructors. It would complicate matters: The parameter would be for the constructor if the constructor were a template, for the struct otherwise. In cases where the struct is templated and the constructor is not, it would apply to the struct. In cases where the struct is concrete and the constructor is templated, it would apply to the constructor. In the case where the struct is templated AND the constructor is templated, it would require the struct to have an explicit instantiation. This is not complex, nor unintuitive. > When you decompose constructors, they are simply fucntions, and IFTI > exists on functions. The same should be allowed for constructors. I completely agree and that's my point. :) The template parameter list of the constructor should stay with the constructor. In the rare cases where the struct and the constructor are templated, it will stay with the constructor. > There is almost no difference between this: > > template foo(T){ > void foo(T t) {} > } > > and this: > > struct foo(T){ > this(T t) {} > } Actually, the latter is a shorthand for this: template S(T) { struct S { T t; this(U)(U) {} } } No, it is shorthand for this: template foo(T) { struct foo { this(T t) {} } } Note there is only ONE template type. For your case, the shorthand would be: struct S(T) { this(U)(U u) {} } As you see, T comes from the outer template and U stays with the constructor. It allows the following use: void main() { auto s = S!int(byte.init); } This would be required if both struct and constructor are templated (and rightly so). -Steve
Re: Question about auto ref
I appreciate your efforts and look forward to the link. :) But I never heard anything about that. How long has it been since that was suggested? But that's honestly sad to hear. I thought I would contribute to the solution of this problem. Then we'll have to wait and continue to hope.
Re: Efficiency of using array as stack
You will likely get better performance if you use: a ~= int.init; instead of: a.length++; So that's a relief, a dynamic array in D actually *is* an efficient queue implementation out of the box, I just did it improperly in the example. Thank you for the correction. With that, the number of relocations in the queue example dropped down to 2. growth of 1024 is when the new pages are tacked onto the end (4096 / sizeof(int)), growth of 891 is interesting. I can explain it though :) Thank you for the very detailed explanation! Knowing how things work down to the bare bones, and the rationale behind that, is definitely helpful, both logically (to write better code) and psychologically (the feeling of things in control). I just hope such quality explanations will be incorporated into some book or manual someday. - Ivan Kazmenko.
Re: When to call setAssertHandler?
On Mar 22, 2013, at 2:58 AM, Benjamin Thaut wrote: > So I want to install my own assertHandler. The problem is, that even if I > call "setAssetHandler" in a shared module constructor, and that module does > not import any other modules, it is still not initialized first. Is there a > way to set the assert before any module constructors run without hacking > druntime? I'm afraid not. I suppose this is a case I should have handled, but it didn't occur to me at the time.
Re: Can std.json handle Unicode?
On Mar 23, 2013, at 5:22 AM, Jacob Carlborg wrote: > I'm wondering because I see that std.json uses isControl, isDigit and > isHexDigit from std.ascii and not std.uni. This also causes a problem with a > pull request I recently made for std.net.isemail. In one of its unit tests > the DEL character (127) is used. According to std.ascii.isControl this is a > control character, but not according to std.uni.isControl. This will cause > the test suite for the pull request not to be run since std.json chokes on > the DEL character. I don't know about control characters, but std.json doesn't handle UTF-16 surrogate pairs in strings, which are legal JSON. I *think* it does properly handle the 32 bit code points though.
Re: Question about auto ref
On Monday, March 25, 2013 23:35:06 Namespace wrote: > > Because the number of instantiations of the template could grow > > exponentially > > as the number of auto ref parameters grows. Being able to use > > the trick with > > the temporary with templated functions could really help reduce > > template bloat > > when the current meaning of auto ref is not necessary, but that > > means coming > > up with a new attribute rather than reusing auto ref with > > non-templated > > functions. > > I use the "trick" with the temporary. But why introduce rather a > new attribute? > I thought the real reason why auto ref was first introduced was > to solve the rvalue ref problem. Now we could do it. So what's > wrong with auto ref for non- > template functions? > I'm afraid that the introducing of a new attribute means to spend > a lot of time. Is that really needed? :/ Or am I wrong? The problem is that we need the temporary trick with templated functions as well as non-templated functions. auto ref on templated functions as it stands is great for creating parameters that retaining all of the attributes on a type - including refness - but it causes template bloat, which in the case that auto ref was originally intended to solve is completely unnecessary. The temporary trick will work just fine for that, but you can't use auto ref for that on templated functions, because we'd lose out on what it currently does, which is needed for forwarding arguments (much as it was accidental that we got that ability). So, in order to have the temporary trick with templated functions, we need a new attribute. That being the caes, there's no point in implementing auto ref for non-templated functions, as they should just use the same attribute as would be used with template functions. > I haven't heard of it. > Would be very nice if you could do it and post the link. :) I can try, but the search of my e-mail client sucks, so it's always a pain for me to find anything in old posts. - Jonathan M Davis
Named Tuple Names
Is there a way to get the names of the fields in a named tuple? It looks like the names are actually aliases. Thanks, JC
Re: Question about auto ref
Because the number of instantiations of the template could grow exponentially as the number of auto ref parameters grows. Being able to use the trick with the temporary with templated functions could really help reduce template bloat when the current meaning of auto ref is not necessary, but that means coming up with a new attribute rather than reusing auto ref with non-templated functions. I use the "trick" with the temporary. But why introduce rather a new attribute? I thought the real reason why auto ref was first introduced was to solve the rvalue ref problem. Now we could do it. So what's wrong with auto ref for non- template functions? I'm afraid that the introducing of a new attribute means to spend a lot of time. Is that really needed? :/ Or am I wrong? Andrei is flat out against this. I wouldn't expect that te over happen. Good to know. We pretty much need a new attribute. IIRC, Kenji had a suggestion for what it would be, but I don't remember what it was now. I'd have to go digging through the archives to find it. - Jonathan M Davis I haven't heard of it. Would be very nice if you could do it and post the link. :)
Re: Question about auto ref
On Monday, March 25, 2013 20:43:29 Namespace wrote: > > Basically, someone needs to implement it and then talk Walter > > into accepting > > it. That'll be easier for someone like Kenji, who's already a > > major > > contributor, but in theory, anyone can do it. It's just that > > there's a high > > risk that the pull request would languish for a while. And it > > would probably > > need to be implemented with a name other than auto ref in order > > to avoid the > > aforementioned problems, and having to agree on that could > > cause further > > delay. > > I am currently working in the required part of the compiler, but > I need help and other opinions. > So far I've tried both: an implementation for auto ref and ref > const. > > -> auto ref: > auto ref for non-template functions. In this case (as you had > suggested it once) temporary variables are created for rvalues. > Thus the behavior of auto ref would be different for template and > non-template functions. But I do not see how that would be > problematic. Because the number of instantiations of the template could grow exponentially as the number of auto ref parameters grows. Being able to use the trick with the temporary with templated functions could really help reduce template bloat when the current meaning of auto ref is not necessary, but that means coming up with a new attribute rather than reusing auto ref with non-templated functions. > -> ref const: > const ref creates for rvalues a temporary variable that is then > passed to the function. Advantage: It is like C++. Disadvantage: > it could break code and you get always a const parameter. Andrei is flat out against this. I wouldn't expect that te over happen. > As I said, I've tried both ways before. But I like to hear other > opinions which of both would be more preferred. > And I would be glad about any kind of help (looking on my code > etc.). > Maybe we could convince Walter and Andrei with a finished > implementation. > I hope that no one like to have a new syntax for this kind of > thing because then we will discuss another year... We pretty much need a new attribute. IIRC, Kenji had a suggestion for what it would be, but I don't remember what it was now. I'd have to go digging through the archives to find it. - Jonathan M Davis
Re: Possible bug
On 03/25/2013 12:40 PM, Steven Schveighoffer wrote: > On Mon, 25 Mar 2013 11:31:17 -0400, Ali Çehreli wrote: > >> This design allows templated constructors: >> >> struct S // <-- not a template >> { >> this(T)(T t) // <-- template >> { >> // ... >> } >> >> // ... >> } >> >> The same in C++... > > Templated constructors would not be disallowed if you allowed IFTI on > templated structs/classes without templated constructors. It would complicate matters: The parameter would be for the constructor if the constructor were a template, for the struct otherwise. > When you decompose constructors, they are simply fucntions, and IFTI > exists on functions. The same should be allowed for constructors. I completely agree and that's my point. :) The template parameter list of the constructor should stay with the constructor. > There is almost no difference between this: > > template foo(T){ > void foo(T t) {} > } > > and this: > > struct foo(T){ > this(T t) {} > } Actually, the latter is a shorthand for this: template S(T) { struct S { T t; this(U)(U) {} } } As you see, T comes from the outer template and U stays with the constructor. It allows the following use: void main() { auto s = S!int(byte.init); } > > -Steve Ali
Re: Question about auto ref
Basically, someone needs to implement it and then talk Walter into accepting it. That'll be easier for someone like Kenji, who's already a major contributor, but in theory, anyone can do it. It's just that there's a high risk that the pull request would languish for a while. And it would probably need to be implemented with a name other than auto ref in order to avoid the aforementioned problems, and having to agree on that could cause further delay. I am currently working in the required part of the compiler, but I need help and other opinions. So far I've tried both: an implementation for auto ref and ref const. -> auto ref: auto ref for non-template functions. In this case (as you had suggested it once) temporary variables are created for rvalues. Thus the behavior of auto ref would be different for template and non-template functions. But I do not see how that would be problematic. -> ref const: const ref creates for rvalues a temporary variable that is then passed to the function. Advantage: It is like C++. Disadvantage: it could break code and you get always a const parameter. As I said, I've tried both ways before. But I like to hear other opinions which of both would be more preferred. And I would be glad about any kind of help (looking on my code etc.). Maybe we could convince Walter and Andrei with a finished implementation. I hope that no one like to have a new syntax for this kind of thing because then we will discuss another year...
Re: Possible bug
On Mon, 25 Mar 2013 11:31:17 -0400, Ali Çehreli wrote: This design allows templated constructors: struct S // <-- not a template { this(T)(T t) // <-- template { // ... } // ... } The same in C++... Templated constructors would not be disallowed if you allowed IFTI on templated structs/classes without templated constructors. When you decompose constructors, they are simply fucntions, and IFTI exists on functions. The same should be allowed for constructors. There is almost no difference between this: template foo(T){ void foo(T t) {} } and this: struct foo(T){ this(T t) {} } -Steve
Re: Possible bug
On Mon, 25 Mar 2013 11:11:40 -0400, Sergei Nosov wrote: On Monday, 25 March 2013 at 14:12:17 UTC, bearophile wrote: Sergei Nosov: Everything's fine if I specify parameters explicitly: test!int hello = test!int(cptr); Some persons have proposed alternative designs, but D is working as currently designed here... Unlike template functions, templated structs don't infer the type. Bye, bearophile Thx, is there any good rationale? There really isn't. I have created an enhancement request that you might be interested in voting for. http://d.puremagic.com/issues/show_bug.cgi?id=6082 Note that auto is your friend here to avoid the dual-specification of the template: auto hello = test!int(cptr); And you can always create a wrapper function: test!T mktest(T)(T *ptr) { return test!T(ptr);} ... auto hello = mktest(cptr); // no explicit instantiation required -Steve
Thrift D bindings: make check broken under ubuntu 12.04. Where to report?
Where or to whom should I report a bug in the thrift D bindings? In recent ubuntu, the maintainers inexplicably changed the linker (ld) defaults to --as-needed, which breaks the 'make check' for Thrifts D binding, presumably because they are using some kind of 'indirect' linking. reproduction: ~/pkg/thrift/thrift/lib/d$ make check # using dmd 2.062 on x86_64. (thrift at a recent version; 3c434ab87d). ... dmd -gc -ofunittest/debug/thrift/server/transport/ssl -unittest -w -wi -I../../lib/d/src -L-levent -L-lssl -L-lcrypto src/thrift/server/transport/ssl.d libthriftd-event.a libthriftd-ssl.a libthriftd.a unittest/emptymain.d libthriftd-ssl.a(ssl_3cd_3af.o): In function `_D6thrift9transport3ssl10TSSLSocket6isOpenMFNdZb': src/thrift/transport/ssl.d:(.text._D6thrift9transport3ssl10TSSLSocket6isOpenMFNdZb+0x71): undefined refe\ rence to `SSL_get_shutdown' ... I can fix this by 1. putting "DFLAGS_PRE=-L--no-as-needed" in dmd.conf and using a dmd branch that makes DFLAGS_PRE work: https://github.com/glycerine/dmd/tree/fix_9805 All this does is pre-pend (instead of append) the contents of DFLAGS_PRE to the dmd command line. or 2. manually compiling with dmd --no-as-needed ... (which is painful, hence the #1 step above is vastly preferred) but somebody smarter than me should probably have a look at the linking in the 'make check' for D's thrift bindings and try to make it work even without --no-as-needed. -J
Re: Possible bug
On 03/25/2013 08:11 AM, Sergei Nosov wrote: > On Monday, 25 March 2013 at 14:12:17 UTC, bearophile wrote: >> Sergei Nosov: >> >>> Everything's fine if I specify parameters explicitly: >>> >>> test!int hello = test!int(cptr); >>> >> >> Some persons have proposed alternative designs, but D is working as >> currently designed here... Unlike template functions, templated >> structs don't infer the type. >> >> Bye, >> bearophile > > Thx, is there any good rationale? This design allows templated constructors: struct S // <-- not a template { this(T)(T t) // <-- template { // ... } // ... } The same in C++... Ali
Re: Efficiency of using array as stack
If you happened to get that accidental blank send, sorry, I tried to cancel it. On Sat, 23 Mar 2013 19:45:21 -0400, Ivan Kazmenko wrote: On Saturday, 23 March 2013 at 19:33:06 UTC, Jonathan M Davis wrote: You might want to check out this article where someone ran into similar issues: https://www.semitwist.com/articles/article/view/don-t-use-arrays-as-stacks And if you haven't read Steven's article on arrays, you should do so: http://dlang.org/d-array-article.html That was a good reading, thank you! The whole matter became clearer for me. But now, I have one more example which confuses me, and the articles don't seem to help right away with it. In this example, I am moving a "sliding window" of length n; now that we're done with the stack, here is a simple usage pattern of the queue. What I do is repeatedly (n times also) add an element to the back of the array and then remove an element from the front of it, keeping the whole queue constantly large. Before the start, I reserve c*n entries for my array, where c is a real number between 1 and 2. I track reallocations by monitoring the address of an element of a which should remain still as long as the array is not reallocated. - import std.algorithm; import std.array; import std.range; import std.stdio; void main () { int n = 2_000_000; double c = 1.5; auto a = array (iota (n)); a.reserve (cast (int) (n * c)); auto prev = &a[$ - 1]; int changes = 0; foreach (i; 0..n) { debug {writeln (a.capacity);} a.length++; a = a[1..$]; auto next = &a[$ - i - 1]; if (prev != next) { changes++; prev = next; } } writeln (changes); } - Now, if I set c to 2, there are no reallocations: all the work goes with the 2*n pre-allocated elements. But as I decrease c down to 1, the number of reallocations grows *linearly*, roughly 1 per 2000 appends. So for c = 1, there are 1044 reallocations in total. And that's still quadratic behavior, albeit divided by a large constant (~2000)! So here is how the appender tries to add data: 1. if the block is less than a page, memory is tracked as a bin of like-sized blocks that fit into a page. Starting at 16-byte blocks, then doubling until you reach half-page size. So if you need something that consumes less than 16-bytes, a 16-byte chunk is allocated out of a 16-byte bin (which is a page that has nothing but 16-byte chunks in it). 2. When you reallocate to a larger block size (16 to 32 for instance), the block MUST be moved into another bin, because only 16-byte blocks are allowed in that bin. 3. When you get to PAGE size (4096 bytes) and larger, the appender takes a different approach: a. If the page following your block is unallocated, and it can simply extend the block into that next page, it will do so. This avoids copying the data to another block, which arguably would be more expensive than trying to double the capacity (not sure if this is true, but that's how it works). b. If not, it will reallocate into a new or existing empty block that can hold the entire data, plus some additional space calculated by an algorithm that is not quite double, but aims to amortize appending (if you search in the lifetime.d file in druntime, look for newCapacity to find the function that calculates this extra space). HOWEVER, setting the length is NOT considered appending by the runtime. The runtime takes a different approach when just setting the length -- it does NOT add any extra capacity to try and amortize the allocations. The idea is that you set the length usually once, and then use the array without appending. It is more efficient if you are appending to give it the elements to append rather than zero-init them first. You will likely get better performance if you use: a ~= int.init; instead of: a.length++; What happens (locally) is, once the array size is not enough, it starts being grown by blocks of 1024 or 891 (?!) elements in a repeating pattern; one of these reallocates, the other does not. The textbook growth implementation suggests doubling the array size, but it looks like D attempts something smarter here. However, in my case, the result is ~8x slower behavior when not pre-allocating. The more is n, the slower is the version without pre-allocation (c = 1) compared to the version with pre-allocation (c = 2). And this means that a D array is not also an efficient queue out-of-the-box. However, as in the case with stack, it could perhaps be efficient with a bit of tweaking (some custom tailored calls to reserve perhaps?). growth of 1024 is when the new pages are tacked onto the end (4096 / sizeof(int)), growth of 891 is interesting. I can explain it
Re: Possible bug
On Monday, 25 March 2013 at 14:12:17 UTC, bearophile wrote: Sergei Nosov: Everything's fine if I specify parameters explicitly: test!int hello = test!int(cptr); Some persons have proposed alternative designs, but D is working as currently designed here... Unlike template functions, templated structs don't infer the type. Bye, bearophile Thx, is there any good rationale?
Re: Possible bug
Sergei Nosov: Everything's fine if I specify parameters explicitly: test!int hello = test!int(cptr); Some persons have proposed alternative designs, but D is working as currently designed here... Unlike template functions, templated structs don't infer the type. Bye, bearophile
Possible bug
Hi! This code doesn't compile with dmd v2.062 on Linux_x86_64 struct test(T) { T *data_; this(T *data) { data_ = data; } } void main() { int *cptr = null; test!int hello = test(cptr); } Error: dmd test.d test.d(12): Error: struct test.test does not match any function template declaration. Candidates are: test.d(2):test.test(T) test.d(12): Error: struct test.test(T) cannot deduce template function from argument types !()(int*) Everything's fine if I specify parameters explicitly: test!int hello = test!int(cptr);