www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - C++17 cannot beat D surely

reply Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
Bj=C3=B6rn Fahller has done compile time sort in C++17 here http://playfulp=
r
ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html

Surely D can do better?

--=20
Russel.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder ekiga.n=
et
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
Jun 03
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Björn Fahller has done compile time sort in C++17 here http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html
 
 Surely D can do better?
There is nothing to do really. Just use standard library sort. void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; static auto b = sort(a); writeln(b); } Andrei
Jun 03
next sibling parent reply Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 2017-06-03 at 13:32 -0400, Andrei Alexandrescu via Digitalmars-
d wrote:
 [=E2=80=A6]
=20
 There is nothing to do really. Just use standard library sort.
=20
 void main() {
 	import std.algorithm, std.stdio;
 	enum a =3D [ 3, 1, 2, 4, 0 ];
 	static auto b =3D sort(a);
 	writeln(b);
 }
=20
But is this sort guaranteed to happen at compile time rather than runtime? --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jun 03
next sibling parent Meta <jared771 gmail.com> writes:
On Saturday, 3 June 2017 at 18:31:37 UTC, Russel Winder wrote:
 On Sat, 2017-06-03 at 13:32 -0400, Andrei Alexandrescu via 
 Digitalmars- d wrote:
 […]
 
 There is nothing to do really. Just use standard library sort.
 
 void main() {
 	import std.algorithm, std.stdio;
 	enum a = [ 3, 1, 2, 4, 0 ];
 	static auto b = sort(a);
 	writeln(b);
 }
 
But is this sort guaranteed to happen at compile time rather than runtime?
Yes: https://dlang.org/spec/function.html#interpretation And there's no jumping through ridiculous hoops, unlike the article.
Jun 03
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2017-06-03 20:31, Russel Winder via Digitalmars-d wrote:

 But is this sort guaranteed to happen at compile time rather than
 runtime?
Yes. It's the context that decides if it occurs at compile time or at runtime. Something declared as "static" or "enum" requires that the value can be evaluated at compile time. That's the beauty of D, the same functions can be used both at compile time and at runtime. -- /Jacob Carlborg
Jun 03
parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 June 2017 at 18:45:56 UTC, Jacob Carlborg wrote:
 On 2017-06-03 20:31, Russel Winder via Digitalmars-d wrote:

 But is this sort guaranteed to happen at compile time rather 
 than
 runtime?
Yes. It's the context that decides if it occurs at compile time or at runtime. Something declared as "static" or "enum" requires that the value can be evaluated at compile time.
Meeep. Wrong. The example is just wrong. 'static auto b = ...' is not a compile-time variable. It's just a variable that's like a global but declared within a function. Remember the singleton pattern using 'static Stuff instance'.
Jun 03
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 3 June 2017 at 20:18:59 UTC, Basile B. wrote:
 On Saturday, 3 June 2017 at 18:45:56 UTC, Jacob Carlborg wrote:
 On 2017-06-03 20:31, Russel Winder via Digitalmars-d wrote:

 But is this sort guaranteed to happen at compile time rather 
 than
 runtime?
Yes. It's the context that decides if it occurs at compile time or at runtime. Something declared as "static" or "enum" requires that the value can be evaluated at compile time.
Meeep. Wrong. The example is just wrong. 'static auto b = ...' is not a compile-time variable. It's just a variable that's like a global but declared within a function. Remember the singleton pattern using 'static Stuff instance'.
Meep. Wrong :) Static initializers for static variables and constants are evaluated at compile time, initializing them with runtime values is a compile-time error. Yes, you can't do a static assert on b. It's still initialized at compile time though.
Jun 03
next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 06/03/2017 10:29 PM, Stanislav Blinov wrote:
 Meep. Wrong :)
 
 Static initializers for static variables and constants are evaluated at 
 compile time, initializing them with runtime values is a compile-time 
 error.
Meep. Meep. I wouldn't say you're wrong, but there's nitpicking to be done. You can't use a run-time value as the initializer, but you *can* initialize a static variable with a run-time value: using a static constructor.
Jun 03
parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 3 June 2017 at 21:04:16 UTC, ag0aep6g wrote:
 On 06/03/2017 10:29 PM, Stanislav Blinov wrote:
 Meep. Wrong :)
 
 Static initializers for static variables and constants are 
 evaluated at compile time, initializing them with runtime 
 values is a compile-time error.
Meep. Meep. I wouldn't say you're wrong, but there's nitpicking to be done. You can't use a run-time value as the initializer, but you *can* initialize a static variable with a run-time value: using a static constructor.
Mental note to self: never write assuming sentences in a NG :) You're correct, of course. I meant inline initialization, as presented in the code in question.
Jun 03
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 June 2017 at 20:29:04 UTC, Stanislav Blinov wrote:
 On Saturday, 3 June 2017 at 20:18:59 UTC, Basile B. wrote:
 On Saturday, 3 June 2017 at 18:45:56 UTC, Jacob Carlborg wrote:
 On 2017-06-03 20:31, Russel Winder via Digitalmars-d wrote:

 But is this sort guaranteed to happen at compile time rather 
 than
 runtime?
Yes. It's the context that decides if it occurs at compile time or at runtime. Something declared as "static" or "enum" requires that the value can be evaluated at compile time.
Meeep. Wrong. The example is just wrong. 'static auto b = ...' is not a compile-time variable. It's just a variable that's like a global but declared within a function. Remember the singleton pattern using 'static Stuff instance'.
Meep. Wrong :) Static initializers for static variables and constants are evaluated at compile time, initializing them with runtime values is a compile-time error. Yes, you can't do a static assert on b. It's still initialized at compile time though.
Actually i know where my error comes from. It comes from "static immutable". Since "static immutable" can be used in place of "enum" i've assumed that this was the real intention and not "static auto...".
Jun 03
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On Saturday, 3 June 2017 at 17:32:41 UTC, Andrei Alexandrescu 
wrote:
 On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Björn Fahller has done compile time sort in C++17 here 
 http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html
 
 Surely D can do better?
There is nothing to do really. Just use standard library sort. void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; static auto b = sort(a); writeln(b); }
I'd say this deserves a blog post but it would be too short. -Steve
Jun 03
next sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 3 June 2017 at 19:12:46 UTC, Steven Schveighoffer 
wrote:
 On Saturday, 3 June 2017 at 17:32:41 UTC, Andrei Alexandrescu 
 wrote:
 On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Björn Fahller has done compile time sort in C++17 here 
 http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html
 
 Surely D can do better?
There is nothing to do really. Just use standard library sort. void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; static auto b = sort(a); writeln(b); }
I'd say this deserves a blog post but it would be too short. -Steve
It already looks like a great blog post as is :)
Jun 03
prev sibling next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 June 2017 at 19:12:46 UTC, Steven Schveighoffer 
wrote:
 On Saturday, 3 June 2017 at 17:32:41 UTC, Andrei Alexandrescu 
 wrote:
 On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Björn Fahller has done compile time sort in C++17 here 
 http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html
 
 Surely D can do better?
There is nothing to do really. Just use standard library sort. void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; static auto b = sort(a); writeln(b); }
I'd say this deserves a blog post but it would be too short. -Steve
Yes but let's correct the mistake first ;-] void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; enum b = sort(a);// static is not CT !!!!! static assert(b[0] == 0); // does not pass with static auto b... writeln(b); }
Jun 03
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03.06.2017 22:16, Basile B. wrote:
 On Saturday, 3 June 2017 at 19:12:46 UTC, Steven Schveighoffer wrote:
 On Saturday, 3 June 2017 at 17:32:41 UTC, Andrei Alexandrescu wrote:
 On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Björn Fahller has done compile time sort in C++17 here http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html

 Surely D can do better?
There is nothing to do really. Just use standard library sort. void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; static auto b = sort(a); writeln(b); }
I'd say this deserves a blog post but it would be too short. -Steve
Yes but let's correct the mistake first ;-] ...
There is no mistake. (But 'auto' is redundant.)
 void main() {
      import std.algorithm, std.stdio;
      enum a = [ 3, 1, 2, 4, 0 ];
      enum b = sort(a);// static is not CT !!!!!
      static assert(b[0] == 0); // does not pass with static auto b...
      writeln(b);
 }
 
 
This is worse. Now there is an allocation at runtime.
Jun 03
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Saturday, 3 June 2017 at 22:18:06 UTC, Timon Gehr wrote:
 There is no mistake. (But 'auto' is redundant.)

 void main() {
      import std.algorithm, std.stdio;
      enum a = [ 3, 1, 2, 4, 0 ];
      enum b = sort(a);// static is not CT !!!!!
      static assert(b[0] == 0); // does not pass with static 
 auto b...
      writeln(b);
 }
 
 
This is worse. Now there is an allocation at runtime.
So maybe we can do a blog post on when to use static or enum? Because smart people don't seem to be agreeing on this...
Jun 03
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/03/2017 07:41 PM, jmh530 wrote:
 On Saturday, 3 June 2017 at 22:18:06 UTC, Timon Gehr wrote:
 There is no mistake. (But 'auto' is redundant.)

 void main() {
      import std.algorithm, std.stdio;
      enum a = [ 3, 1, 2, 4, 0 ];
      enum b = sort(a);// static is not CT !!!!!
      static assert(b[0] == 0); // does not pass with static auto b...
      writeln(b);
 }
This is worse. Now there is an allocation at runtime.
So maybe we can do a blog post on when to use static or enum? Because smart people don't seem to be agreeing on this...
Yes please! cc Mike. -- Andrei
Jun 03
parent reply Mike Parker <aldacron gmail.com> writes:
On Sunday, 4 June 2017 at 03:28:32 UTC, Andrei Alexandrescu wrote:
 On 06/03/2017 07:41 PM, jmh530 wrote:
 On Saturday, 3 June 2017 at 22:18:06 UTC, Timon Gehr wrote:
 There is no mistake. (But 'auto' is redundant.)

 void main() {
      import std.algorithm, std.stdio;
      enum a = [ 3, 1, 2, 4, 0 ];
      enum b = sort(a);// static is not CT !!!!!
      static assert(b[0] == 0); // does not pass with static 
 auto b...
      writeln(b);
 }
This is worse. Now there is an allocation at runtime.
So maybe we can do a blog post on when to use static or enum? Because smart people don't seem to be agreeing on this...
Yes please! cc Mike. -- Andrei
Any volunteers? This one surprised me. Looking at the disassembly over at godbolt, I see this when using enum b = sort(a): ``` lea rax, [rbp-64] mov QWORD PTR [rax], 0 mov QWORD PTR [rax+8], 0 mov QWORD PTR [rbp-48], 0 mov QWORD PTR [rbp-40], 0 mov DWORD PTR [rbp-32], 0 mov DWORD PTR [rbp-44], 1 mov DWORD PTR [rbp-40], 2 mov DWORD PTR [rbp-36], 3 mov DWORD PTR [rbp-32], 4 mov esi, 5 mov edi, OFFSET FLAT:_D11TypeInfo_Ai6__initZ call _d_arrayliteralTX mov rdx, QWORD PTR [rbp-48] mov QWORD PTR [rax], rdx mov rdx, QWORD PTR [rbp-40] mov QWORD PTR [rax+8], rdx mov edx, DWORD PTR [rbp-32] mov DWORD PTR [rax+16], edx mov QWORD PTR [rbp-64], 5 mov QWORD PTR [rbp-56], rax mov rax, QWORD PTR [rbp-64] mov rdx, QWORD PTR [rbp-56] mov rcx, rax mov rbx, rdx mov rax, rdx mov rdi, rcx mov rsi, rax call writeln ``` And this when using static b = sort(a) (and the same with static immutable b): ``` mov rdx, QWORD PTR fs:std.range.SortedRange!(int[], "a < b").SortedRange example.main().b tpoff mov rax, QWORD PTR fs:std.range.SortedRange!(int[], "a < b").SortedRange example.main().b tpoff+8 mov rdi, rdx mov rsi, rax call writeln ``` 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.
Jun 03
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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)
Jun 03
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
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)
Right, but I was under the impression that was only for direct use of the enum literal: enum a = [1, 2, 3]; auto b = a; I thought that assigning the result of a function call to an enum would force a compile-time evaluation of the function, so I would expect enum b = call(lit) to be identical to static immutable b = call(lit).
Jun 03
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Sunday, 4 June 2017 at 04:47:56 UTC, Mike Parker wrote:
 On Sunday, 4 June 2017 at 04:39:21 UTC, Adam D. Ruppe wrote:
 I thought that assigning the result of a function call to an 
 enum would force a compile-time evaluation of the function, so 
 I would expect enum b = call(lit) to be identical to static 
 immutable b = call(lit).
Nevermind. I see where I got mixed up.
Jun 03
prev sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sunday, June 04, 2017 04:47:56 Mike Parker via Digitalmars-d wrote:
 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)
Right, but I was under the impression that was only for direct use of the enum literal: enum a = [1, 2, 3]; auto b = a; I thought that assigning the result of a function call to an enum would force a compile-time evaluation of the function, so I would expect enum b = call(lit) to be identical to static immutable b = call(lit).
As the enum has no address, it can't store anything. So, _anything_ that's an enum is going to be effectively copy-pasted everywhere that it's used. The compiler is smart enough to just copy-past the result and not the expression, but the result still must be copied, and in the case of a dynamic array, that means an allocation. - Jonathan M Davis
Jun 03
parent Mike Parker <aldacron gmail.com> writes:
On Sunday, 4 June 2017 at 05:12:13 UTC, Jonathan M Davis wrote:

 As the enum has no address, it can't store anything. So, 
 _anything_ that's an enum is going to be effectively 
 copy-pasted everywhere that it's used. The compiler is smart 
 enough to just copy-past the result and not the expression, but 
 the result still must be copied, and in the case of a dynamic 
 array, that means an allocation.

 - Jonathan M Davis
Yeah, it hit me after my first reply to Adam. I'm in the middle of putting together a blog post right now.
Jun 03
prev sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
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]);
Jun 06
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/6/17 8:28 PM, Yuxuan Shui wrote:
 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]);
I think it's because the compiler isn't smart enough to pull out the allocation for SortedRange!(...)([0,1,2,3,4])[1], but it is smart enough to know that [0,1,2,3,4][1] does not need to allocate. But it is pretty well known that enum'ing an array can have it allocate wherever it is used. For example, if you do this: enum b = a.sort.array; auto c = b; It will allocate. If you do: auto d = b; It will allocate again. That is an interesting artifact though. Another good reason to use static. -Steve
Jun 06
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/06/2017 06:09 PM, Steven Schveighoffer wrote:

 But it is pretty well known that enum'ing an array can have it allocate
 wherever it is used.
One of the most effective examples is comparing .ptr with (seemingly) itself: void main() { enum e = [ 1 ]; static assert(e.ptr != e.ptr); assert(e.ptr != e.ptr); } Both asserts pass. I'm surprised that e.ptr is usable at compile time. Fine, I guess... :) Ali
Jun 06
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/06/2017 08:06 PM, Ali Çehreli wrote:

     enum e = [ 1 ];
     static assert(e.ptr != e.ptr);
 I'm surprised that e.ptr is usable at compile time.
Sorry to notice this late but printing that ptr exposes the copy-paste behavior of enums: pragma(msg, e.ptr); Outputs &[1][0] That makes sense. It's still interesting that static assert accepts that address comparison. I guess it knows that the result is always false. Ali
Jun 06
prev sibling next sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Wednesday, 7 June 2017 at 03:06:34 UTC, Ali Çehreli wrote:
 On 06/06/2017 06:09 PM, Steven Schveighoffer wrote:

 But it is pretty well known that enum'ing an array can have
it allocate
 wherever it is used.
One of the most effective examples is comparing .ptr with (seemingly) itself: void main() { enum e = [ 1 ]; static assert(e.ptr != e.ptr); assert(e.ptr != e.ptr); } Both asserts pass. I'm surprised that e.ptr is usable at compile time. Fine, I guess... :) Ali
A bit OT, but how about this one? struct Tree { struct Node { Node* left, right; } Node* root = new Node; } void main() { Tree tree1, tree2; assert(tree1.root); assert(tree2.root); assert(tree1.root != tree2.root); // fails } Not `static`, not `enum`, but `new` at compile time and `root` is of course statically initialized :)
Jun 06
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/6/2017 8:06 PM, Ali Çehreli wrote:
 On 06/06/2017 06:09 PM, Steven Schveighoffer wrote:
 
  > But it is pretty well known that enum'ing an array can have it allocate
  > wherever it is used.
 
 One of the most effective examples is comparing .ptr with (seemingly) itself:
 
 void main() {
      enum e = [ 1 ];
      static assert(e.ptr != e.ptr);
      assert(e.ptr != e.ptr);
 }
 
 Both asserts pass. I'm surprised that e.ptr is usable at compile time. Fine, I 
 guess... :)
One trouble with making them the same is if one of the users of e changes an element. Do the rest of the users see the change or the original?
Jun 06
prev sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 3 June 2017 at 23:41:37 UTC, jmh530 wrote:
 On Saturday, 3 June 2017 at 22:18:06 UTC, Timon Gehr wrote:
 There is no mistake. (But 'auto' is redundant.)

 void main() {
      import std.algorithm, std.stdio;
      enum a = [ 3, 1, 2, 4, 0 ];
      enum b = sort(a);// static is not CT !!!!!
      static assert(b[0] == 0); // does not pass with static 
 auto b...
      writeln(b);
 }
 
 
This is worse. Now there is an allocation at runtime.
So maybe we can do a blog post on when to use static or enum? Because smart people don't seem to be agreeing on this...
In General, prefer static immutable.
Jun 03
prev sibling next sibling parent Tourist <gravatar gravatar.com> writes:
On Saturday, 3 June 2017 at 19:12:46 UTC, Steven Schveighoffer 
wrote:
 On Saturday, 3 June 2017 at 17:32:41 UTC, Andrei Alexandrescu 
 wrote:
 On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Björn Fahller has done compile time sort in C++17 here 
 http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html
 
 Surely D can do better?
There is nothing to do really. Just use standard library sort. void main() { import std.algorithm, std.stdio; enum a = [ 3, 1, 2, 4, 0 ]; static auto b = sort(a); writeln(b); }
I'd say this deserves a blog post but it would be too short. -Steve
Title would be longer: Don't bring a knife to a gun fight especially if it is a knife made of a spoon, a toothbrush, duct tape and a shoelace
Jun 03
prev sibling next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/03/2017 12:12 PM, Steven Schveighoffer wrote:

 I'd say this deserves a blog post but it would be too short.
I made many good friends at C++Now. Some of them know Atila from CppCon and other C++ conferences. (Beer involved. :) ) They told me Atila would routinely tell them during C++ presentations "This wouldn't be a talk at a DConf; it's a language feature in D." :) Ali
Jun 03
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Sat, Jun 03, 2017 at 03:00:56PM -0700, Ali ehreli via Digitalmars-d wrote:
 On 06/03/2017 12:12 PM, Steven Schveighoffer wrote:
 
 I'd say this deserves a blog post but it would be too short.
I made many good friends at C++Now. Some of them know Atila from CppCon and other C++ conferences. (Beer involved. :) ) They told me Atila would routinely tell them during C++ presentations "This wouldn't be a talk at a DConf; it's a language feature in D." :)
[...] In this case, I'd say "this wouldn't be an article about D; it's a language feature." :-D Though I'd say we *could* add meat to the article by explaining what exactly CTFE is, how it works, and why you could just call the standard library sort at compile-time and have it Just Work(tm) without having to jump through hoops. And perhaps demonstrate how easy it is to do this not just with sort, but with far more complex things. In fact, significant chunks of Phobos are now available at CTFE. For example, you can call std.format at compile-time to perform some pretty hairy string formatting and have the result baked into your executable so that you incur none of the cost of computing it at runtime. The best part of all this is, as long as you have already written runtime code that's CTFE-compatible, you don't have to do anything else to make it work at compile-time. No messing around with constexpr, no awkward special syntax, no need to jump through hoops, invoke arcane black magic, etc.. Just call the code with normal runtime syntax from an expression whose value needs to be known at compile-time, and the compiler does the rest of you. And if you need a particular functionality both at compile-time and during runtime, there's no need to write it twice in two different sublanguages. You just write one function once, and call it from both CTFE and at runtime. It Just Works(tm). Then we could add the icing on the cake by showing off one of Andrei's(?) little gems in std.random: a RNG generator that checks *at compile-time* whether a particular set of RNG parameters would produce a poor-quality RNG, and abort with a compile-error if so. Meaning that if the thing compiles at all, you have a minimum quality guarantee. (This particular gem is described in detail in TDPL, btw, and is one of the things about D that blew me away when I first read it.) T -- Valentine's Day: an occasion for florists to reach into the wallets of nominal lovers in dire need of being reminded to profess their hypothetical love for their long-forgotten.
Jun 03
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Sunday, 4 June 2017 at 05:38:24 UTC, H. S. Teoh wrote:

 And if you need a particular functionality both at compile-time 
 and during runtime, there's no need to write it twice in two 
 different sublanguages. You just write one function once, and 
 call it from both CTFE and at runtime. It Just Works(tm).
...except when you have `if (__ctfe)` :P
Jun 03
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Sun, Jun 04, 2017 at 06:08:28AM +0000, Stanislav Blinov via Digitalmars-d
wrote:
 On Sunday, 4 June 2017 at 05:38:24 UTC, H. S. Teoh wrote:
 
 And if you need a particular functionality both at compile-time and
 during runtime, there's no need to write it twice in two different
 sublanguages. You just write one function once, and call it from
 both CTFE and at runtime. It Just Works(tm).
...except when you have `if (__ctfe)` :P
Ah, but if you want your function to work both at CTFE and runtime, then why write `if (__ctfe)` in the first place? :-D Unless, of course, you're optimizing for runtime with something that's incompatible with CTFE, like inline assembly or something. Then you're on your own. :-D T -- People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG
Jun 03
parent Jacob Carlborg <doob me.com> writes:
On 2017-06-04 08:18, H. S. Teoh via Digitalmars-d wrote:

 Ah, but if you want your function to work both at CTFE and runtime, then
 why write `if (__ctfe)` in the first place? :-D

 Unless, of course, you're optimizing for runtime with something that's
 incompatible with CTFE, like inline assembly or something.  Then you're
 on your own. :-D
Or using malloc/free at runtime but the GC at compile time. -- /Jacob Carlborg
Jun 04
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Saturday, June 03, 2017 22:38:24 H. S. Teoh via Digitalmars-d wrote:
 On Sat, Jun 03, 2017 at 03:00:56PM -0700, Ali ehreli via Digitalmars-d 
wrote:
 On 06/03/2017 12:12 PM, Steven Schveighoffer wrote:
 I'd say this deserves a blog post but it would be too short.
I made many good friends at C++Now. Some of them know Atila from CppCon and other C++ conferences. (Beer involved. :) ) They told me Atila would routinely tell them during C++ presentations "This wouldn't be a talk at a DConf; it's a language feature in D." :)
[...] In this case, I'd say "this wouldn't be an article about D; it's a language feature." :-D Though I'd say we *could* add meat to the article by explaining what exactly CTFE is, how it works, and why you could just call the standard library sort at compile-time and have it Just Work(tm) without having to jump through hoops. And perhaps demonstrate how easy it is to do this not just with sort, but with far more complex things. In fact, significant chunks of Phobos are now available at CTFE. For example, you can call std.format at compile-time to perform some pretty hairy string formatting and have the result baked into your executable so that you incur none of the cost of computing it at runtime. The best part of all this is, as long as you have already written runtime code that's CTFE-compatible, you don't have to do anything else to make it work at compile-time. No messing around with constexpr, no awkward special syntax, no need to jump through hoops, invoke arcane black magic, etc.. Just call the code with normal runtime syntax from an expression whose value needs to be known at compile-time, and the compiler does the rest of you. And if you need a particular functionality both at compile-time and during runtime, there's no need to write it twice in two different sublanguages. You just write one function once, and call it from both CTFE and at runtime. It Just Works(tm). Then we could add the icing on the cake by showing off one of Andrei's(?) little gems in std.random: a RNG generator that checks *at compile-time* whether a particular set of RNG parameters would produce a poor-quality RNG, and abort with a compile-error if so. Meaning that if the thing compiles at all, you have a minimum quality guarantee. (This particular gem is described in detail in TDPL, btw, and is one of the things about D that blew me away when I first read it.)
Be careful, or Mike will start hounding you to write the actual article. ;) - Jonathan M Davis
Jun 04
parent Mike Parker <aldacron gmail.com> writes:
On Sunday, 4 June 2017 at 07:49:36 UTC, Jonathan M Davis wrote:

 Be careful, or Mike will start hounding you to write the actual 
 article. ;)

 - Jonathan M Davis
It's already written! And I'm looking for reviewers [1] so I can get it in shape in time to publish Monday. [1] http://forum.dlang.org/post/mosjryaaatmhqcpimmbs forum.dlang.org
Jun 04
prev sibling parent Atila Neves <atila.neves gmail.com> writes:
On Saturday, 3 June 2017 at 22:00:56 UTC, Ali Çehreli wrote:
 On 06/03/2017 12:12 PM, Steven Schveighoffer wrote:

 I'd say this deserves a blog post but it would be too short.
I made many good friends at C++Now. Some of them know Atila from CppCon and other C++ conferences. (Beer involved. :) ) They told me Atila would routinely tell them during C++ presentations "This wouldn't be a talk at a DConf; it's a language feature in D." :)
Beer involved. Conference. And they knew _me_? *Shocked* :P There were two distinct talks at CppCon2017 involving some seriously crazy C++ metaprogramming that I said that about. Very interesting how they made the compiler bend over backwards, very high-level stuff. Then when everyone was leaving the room I couldn't help but think that nobody would even mention those techniques in D, you'd get the job done in 5min. Atila
Jun 05
prev sibling next sibling parent reply Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 2017-06-03 at 19:12 +0000, Steven Schveighoffer via
Digitalmars-d wrote:
 On Saturday, 3 June 2017 at 17:32:41 UTC, Andrei Alexandrescu=C2=A0
 wrote:
 On 06/03/2017 01:03 PM, Russel Winder via Digitalmars-d wrote:
 Bj=C3=B6rn Fahller has done compile time sort in C++17 here=C2=A0
 http://playfulpr
 ogramming.blogspot.co.uk/2017/06/constexpr-quicksort-in-c17.html
=20
 Surely D can do better?
=20 There is nothing to do really. Just use standard library sort. =20 void main() { import std.algorithm, std.stdio; enum a =3D [ 3, 1, 2, 4, 0 ]; static auto b =3D sort(a); writeln(b); }
=20 I'd say this deserves a blog post but it would be too short. =20 -Steve
a. that was my point in making the original post; and b. no it isn't, it is the right length. It would make a great article for Overload. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jun 04
parent reply Vittorio Romeo <vittorio.romeo outlook.com> writes:
Could someone clarify why the generated assembly for

void main()  nogc {
     import std.algorithm;
     enum a = [3, 1, 2, 0]; // inferred to be int[]
     enum b = sort(a);
     static assert(b[0] == 0);
}

is 1380 lines with ldc 1.3.0 (-O3 -release -betterC -flto=full)?
You can see the result on godbolt here:
https://godbolt.org/g/BNRnO9

It's kind of surprising compared to C++'s 2 lines:
https://godbolt.org/g/vXrxaY
Jun 04
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 04/06/2017 11:06 AM, Vittorio Romeo wrote:
 Could someone clarify why the generated assembly for
 
 void main()  nogc {
      import std.algorithm;
      enum a = [3, 1, 2, 0]; // inferred to be int[]
      enum b = sort(a);
      static assert(b[0] == 0);
 }
 
 is 1380 lines with ldc 1.3.0 (-O3 -release -betterC -flto=full)?
 You can see the result on godbolt here:
 https://godbolt.org/g/BNRnO9
 
 It's kind of surprising compared to C++'s 2 lines:
 https://godbolt.org/g/vXrxaY
_Dmain is exactly 2 instructions, so nope equivalent :) The linker isn't stripping out unused symbols however (from what I can tell).
Jun 04
parent reply Vittorio Romeo <vittorio.romeo outlook.com> writes:
On Sunday, 4 June 2017 at 10:21:16 UTC, rikki cattermole wrote:
 On 04/06/2017 11:06 AM, Vittorio Romeo wrote:
 Could someone clarify why the generated assembly for
 
 void main()  nogc {
      import std.algorithm;
      enum a = [3, 1, 2, 0]; // inferred to be int[]
      enum b = sort(a);
      static assert(b[0] == 0);
 }
 
 is 1380 lines with ldc 1.3.0 (-O3 -release -betterC 
 -flto=full)?
 You can see the result on godbolt here:
 https://godbolt.org/g/BNRnO9
 
 It's kind of surprising compared to C++'s 2 lines:
 https://godbolt.org/g/vXrxaY
_Dmain is exactly 2 instructions, so nope equivalent :) The linker isn't stripping out unused symbols however (from what I can tell).
I see. Is there any argument that can be passed to ldc in order to strip the unused symbols?
Jun 04
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 04/06/2017 11:27 AM, Vittorio Romeo wrote:
 On Sunday, 4 June 2017 at 10:21:16 UTC, rikki cattermole wrote:
 On 04/06/2017 11:06 AM, Vittorio Romeo wrote:
 Could someone clarify why the generated assembly for

 void main()  nogc {
      import std.algorithm;
      enum a = [3, 1, 2, 0]; // inferred to be int[]
      enum b = sort(a);
      static assert(b[0] == 0);
 }

 is 1380 lines with ldc 1.3.0 (-O3 -release -betterC -flto=full)?
 You can see the result on godbolt here:
 https://godbolt.org/g/BNRnO9

 It's kind of surprising compared to C++'s 2 lines:
 https://godbolt.org/g/vXrxaY
_Dmain is exactly 2 instructions, so nope equivalent :) The linker isn't stripping out unused symbols however (from what I can tell).
I see. Is there any argument that can be passed to ldc in order to strip the unused symbols?
Should be a way, since you can pass arg directly via ldc to ld. But I would expect it to have done it by default anyway.
Jun 04
parent David Nadlinger <code klickverbot.at> writes:
On Sunday, 4 June 2017 at 10:39:09 UTC, rikki cattermole wrote:
 Should be a way, since you can pass arg directly via ldc to ld. 
 But I would expect it to have done it by default anyway.
It is indeed done by default on Windows and Linux. If you dump the object code before it gets to the linker, it will still show the unused symbols, though. — David
Jun 04
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 4 June 2017 at 10:27:14 UTC, Vittorio Romeo wrote:
 I see. Is there any argument that can be passed to ldc in order 
 to strip the unused symbols?
Doesn't the strip command work?
Jun 04
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 4 June 2017 at 14:13:24 UTC, Ola Fosheim Grøstad wrote:
 On Sunday, 4 June 2017 at 10:27:14 UTC, Vittorio Romeo wrote:
 I see. Is there any argument that can be passed to ldc in 
 order to strip the unused symbols?
Doesn't the strip command work?
Oh wait, you didn't mean symbols, you meant code. LLVM has passes for that: https://blog.quarkslab.com/global-dead-code-elimination-for-llvm-revisited.html
Jun 04
prev sibling parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Saturday, 3 June 2017 at 19:12:46 UTC, Steven Schveighoffer 
wrote:
 I'd say this deserves a blog post but it would be too short.
Actually i wouldn't mind a vlog or some short presentations on a variety of subjects. Maybe even continuations of presentations that could have been at the Dlang conference except weren't due to time constraints.
Jun 06
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 6 June 2017 at 08:00:11 UTC, Era Scarecrow wrote:
 On Saturday, 3 June 2017 at 19:12:46 UTC, Steven Schveighoffer 
 wrote:
 I'd say this deserves a blog post but it would be too short.
Actually i wouldn't mind a vlog or some short presentations on a variety of subjects. Maybe even continuations of presentations that could have been at the Dlang conference except weren't due to time constraints.
I could post a video about a simple ctfe transcompiler. or sqlite-d. I have to wait until my computer is fixed though.
Jun 06