digitalmars.D - Is there any hope for "lazy" and nogc?
- Shachar Shemesh (20/20) Jul 31 2018 I'm trying to figure out what's the signature of the built-in assert. It...
- rikki cattermole (3/5) Jul 31 2018 That is because it isn't a function.
- Mike Franklin (37/41) Jul 31 2018 I'm not sure why you want a different assert, but you can
- Shachar Shemesh (10/11) Jul 31 2018 You are. I want something along the lines of:
- Guillaume Boucher (20/26) Jul 31 2018 What D really needs is power asserts. assertEQ's and its
- Seb (5/11) Jul 31 2018 You could also vote for this PR
- Jacob Carlborg (13/31) Jul 31 2018 It seems this is a limitation in the syntax. It works with an explicit
- Steven Schveighoffer (10/22) Jul 31 2018 Hm... I would say compiler should be smart enough to know that lazy
- ag0aep6g (16/18) Jul 31 2018 Looks like you can do it with a "lazy variadic function" [1], but it's
- Shachar Shemesh (7/29) Aug 01 2018 Thank you! Finally!
- Steven Schveighoffer (10/17) Aug 01 2018 The lazy variadic thing is a distinction between specifying variadic
- Shachar Shemesh (18/41) Aug 01 2018 import std.string;
- Iain Buclaw (20/63) Aug 01 2018 My first thought was to have a look at enforce(), but on closer
- Seb (2/24) Aug 02 2018 Isn't this https://issues.dlang.org/show_bug.cgi?id=12647?
- Iain Buclaw (5/37) Aug 03 2018 Seems so, good to know. I'll bookmark it for when I get time to do
- Shachar Shemesh (5/7) Aug 01 2018 I have now read that sentence 4 times, and I still have no idea what it
- Steven Schveighoffer (48/56) Aug 02 2018 import std.stdio;
- Jacob Carlborg (6/13) Aug 04 2018 I'm surprised that this doesn't need to be called with a delegate
- Steven Schveighoffer (4/19) Aug 04 2018 See one of the earlier posts, it's a lazy variadic function. A
- Jacob Carlborg (4/11) Aug 04 2018 Adding @nogc to this example works.
- Nick Treleaven (4/5) Aug 05 2018 Interesting, thanks. I've made a pull to add a See Also link
- Jacob Carlborg (27/45) Aug 04 2018 Based on what Steven said and what I found in the spec, this seems to
I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself. First attempt: void myAssert(bool cond, string msg) nogc nothrow; No, because msg gets evaluated unconditionally. void myAssert(bool cond, lazy string msg) nogc nothrow; test.d(8): Error: nogc function test.myAssert cannot call non- nogc delegate msg void myAssert(bool cond, lazy string msg nogc nothrow ) nogc nothrow; test.d(4): Error: found when expecting ) test.d(4): Error: semicolon expected following function declaration test.d(4): Error: no identifier for declarator nogc test.d(4): Error: declaration expected, not ) test.d(9): Error: unrecognized declaration Templates to the rescue!!! void myAssert(STR)(bool cond, lazy STR msg ); test.d(14): Error: nogc function D main cannot call non- nogc function test.myAssert!string.myAssert Help?? Shachar
Jul 31 2018
On 31/07/2018 7:17 PM, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself.That is because it isn't a function. It's a language feature that is backed by functions.
Jul 31 2018
On Tuesday, 31 July 2018 at 07:17:34 UTC, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself. Help??I'm not sure why you want a different assert, but you can consider these options. 1) Assign your own assert handler: https://github.com/dlang/druntime/blob/52d3fe02272d16d32c150ce6f78bc00241a9dd5d/src/core/exception.d#L393 2) You can provide your own implementations of the runtime hooks at https://github.com/dlang/druntime/blob/cb5efa9854775c5a72acd6870083b16e5ebba369/src/core/exception.d#L628 extern(C) void _d_assertp(immutable(char)* file, uint line) { import core.stdc.stdio; printf("Houston, we have a problem at %s:%u\n", file, line); } void main() { assert(false); } https://run.dlang.io/is/QZEO9W 3) -betterC seems to forward runtime assertions to the C implementation. See https://run.dlang.io/is/QZEO9W For that you have to provide a new implementation of `__assert`: extern(C) void __assert(const char *msg, const char *file, int line) { import core.stdc.stdio; printf("Houston, we have a problem at %s:%u\n", file, line); } extern(C) void main() { assert(false); } https://run.dlang.io/is/D5JxCT 4) Otherwise can't you just implement two `myAssert` overloads? `void assert(bool condition, string msg);` `void assert(bool condition)` Please clarify if I'm missing the point. Mike
Jul 31 2018
On 31/07/18 10:29, Mike Franklin wrote:Please clarify if I'm missing the point.You are. I want something along the lines of: assertEQ(a, b, "a and b are not equal"); When run, it would issue an assert that says: Assertion failed: 3!=7: a and b are not equal Hooking it later is not an option. I am actually interested in a different assert like function. Whether for asserts or otherwise, the "lazy" feature is completely incompatible with function attributes, and that's not good. Shachar
Jul 31 2018
On Tuesday, 31 July 2018 at 07:49:40 UTC, Shachar Shemesh wrote:On 31/07/18 10:29, Mike Franklin wrote:What D really needs is power asserts. assertEQ's and its companions (assertLT, assertLE, ...) feel just like hacks. Power asserts come from Groovy and look like this assert calc(x,y) == [x,z].sum() | | | | | | | 15 2 7 | 2 5 7 false A poorer version exists in C++ (https://www.boost.org/doc/libs/1_67_0/libs/test/doc/html/boost_test/testing_tools/boost_test_universal_macro.html) and of course any language with decent metaprogramming facilities can implement them as a library solution (such as Rust: https://github.com/gifnksm/power-assert-rs and Go: https://github.com/ToQoz/gopwt). If you can not go the route of metaprogramming, provide an assert backend (Javascript: https://github.com/power-assert-js/power-assert). D needs something like this as well, and you can not get there just with lazy.Please clarify if I'm missing the point.You are. I want something along the lines of: assertEQ(a, b, "a and b are not equal"); When run, it would issue an assert that says: Assertion failed: 3!=7: a and b are not equal
Jul 31 2018
On Tuesday, 31 July 2018 at 07:49:40 UTC, Shachar Shemesh wrote:On 31/07/18 10:29, Mike Franklin wrote:You could also vote for this PR (https://github.com/dlang/dmd/pull/8517) - this PR will generate such error messages. It's intended to work in -betterC and nogc (once the PR is ready).Please clarify if I'm missing the point.You are. I want something along the lines of: assertEQ(a, b, "a and b are not equal"); When run, it would issue an assert that says: Assertion failed: 3!=7: a and b are not equal
Jul 31 2018
On 2018-07-31 09:17, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself. First attempt: void myAssert(bool cond, string msg) nogc nothrow; No, because msg gets evaluated unconditionally. void myAssert(bool cond, lazy string msg) nogc nothrow; test.d(8): Error: nogc function test.myAssert cannot call non- nogc delegate msg void myAssert(bool cond, lazy string msg nogc nothrow ) nogc nothrow; test.d(4): Error: found when expecting ) test.d(4): Error: semicolon expected following function declaration test.d(4): Error: no identifier for declarator nogc test.d(4): Error: declaration expected, not ) test.d(9): Error: unrecognized declaration Templates to the rescue!!! void myAssert(STR)(bool cond, lazy STR msg ); test.d(14): Error: nogc function D main cannot call non- nogc function test.myAssert!string.myAssertIt seems this is a limitation in the syntax. It works with an explicit delegate, but then that is required at the call site as well. A lazy parameter is basically just a delegate with a nicer syntax. void myAssert(bool cond, string delegate() nogc nothrow msg) nogc nothrow { auto a = msg(); } Support for adding UDAs to function parameters was recently added. Perhaps we need to support other attributes as well. Please report an issue to http://issues.dlang.org. -- /Jacob Carlborg
Jul 31 2018
On 7/31/18 3:17 AM, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself. First attempt: void myAssert(bool cond, string msg) nogc nothrow; No, because msg gets evaluated unconditionally. void myAssert(bool cond, lazy string msg) nogc nothrow; test.d(8): Error: nogc function test.myAssert cannot call non- nogc delegate msgHm... I would say compiler should be smart enough to know that lazy string messages that are not nogc shouldn't be able to be passed in here. e.g.: myAssert(a == b, "a and b should be equal); // ok myAssert(a == b, a.name ~ " and " ~ b.name ~ " should be equal"); // error It appears that lazy is not inferring anything, it's strictly transformed into a normal delegate. I'd say at least the template solution should be made to work. -Steve
Jul 31 2018
On 07/31/2018 09:17 AM, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself.Looks like you can do it with a "lazy variadic function" [1], but it's not pretty: ---- alias Dg = string delegate() nogc nothrow; void myAssert(bool cond, Dg[1] msg_dg ...) nogc nothrow { import core.stdc.stdio; if (!cond) { string msg = msg_dg[0](); printf("%*s\n", msg.length, msg.ptr); } } ---- [1] https://dlang.org/spec/function.html#lazy_variadic_functions
Jul 31 2018
Thank you! Finally! Let me just state, for the record, that having *yet another* syntax special case is just appalling. With that said, I was hoping that specifying it explicitly as a delegate would allow me to scope it. Apparently, that doesn't work :-( Shachar On 31/07/18 23:03, ag0aep6g wrote:On 07/31/2018 09:17 AM, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself.Looks like you can do it with a "lazy variadic function" [1], but it's not pretty: ---- alias Dg = string delegate() nogc nothrow; void myAssert(bool cond, Dg[1] msg_dg ...) nogc nothrow { import core.stdc.stdio; if (!cond) { string msg = msg_dg[0](); printf("%*s\n", msg.length, msg.ptr); } } ---- [1] https://dlang.org/spec/function.html#lazy_variadic_functions
Aug 01 2018
On 8/1/18 3:59 AM, Shachar Shemesh wrote:Thank you! Finally! Let me just state, for the record, that having *yet another* syntax special case is just appalling.The lazy variadic thing is a distinction between specifying variadic lazy parameters and a lazy variadic array. The distinction is so miniscule, but necessary to have a disambiguous syntax. But I had actually thought for a while, that you could simply specify a delegate, and it would be treated as a lazy parameter, which would probably solve your problem. I really think this syntax should be available.With that said, I was hoping that specifying it explicitly as a delegate would allow me to scope it. Apparently, that doesn't work :-(I guess you mean you can't scope the delegates? I'm surprised if that doesn't work. -Steve
Aug 01 2018
On 01/08/18 17:13, Steven Schveighoffer wrote:On 8/1/18 3:59 AM, Shachar Shemesh wrote:import std.string; alias Dg = string delegate() nogc nothrow; void myAssert(bool cond, scope Dg[1] msg_dg ...) nogc nothrow { import core.stdc.stdio; if (!cond) { string msg = msg_dg[0](); printf("%*s\n", msg.length, msg.ptr); } } void main() nogc { string msg = "Hello"; myAssert(true, msg); // <- errors on this line } It errors out: complains it needs to allocate main's frame on the GC, but main is nogc. The same happens if I move the scope to the alias.Thank you! Finally! Let me just state, for the record, that having *yet another* syntax special case is just appalling.The lazy variadic thing is a distinction between specifying variadic lazy parameters and a lazy variadic array. The distinction is so miniscule, but necessary to have a disambiguous syntax. But I had actually thought for a while, that you could simply specify a delegate, and it would be treated as a lazy parameter, which would probably solve your problem. I really think this syntax should be available.With that said, I was hoping that specifying it explicitly as a delegate would allow me to scope it. Apparently, that doesn't work :-(I guess you mean you can't scope the delegates? I'm surprised if that doesn't work. -Steve
Aug 01 2018
On 1 August 2018 at 18:52, Shachar Shemesh via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 01/08/18 17:13, Steven Schveighoffer wrote:My first thought was to have a look at enforce(), but on closer observation it is neither nogc or nothrow. Maybe you should raise a bug report? It's certainly worth an attempt to bridge these two features together. I think it makes sense enough that lazy parameters should infer attributes from the function, and that it should be an error to pass a parameter that does not meet those constraints. i.e: --- // Signatures. void myAssert(bool cond, lazy string msg) nogc nothrow; string mayAlloc() nothrow; string mayThrow() nogc; // Code myAssert(cond, mayAlloc()); // violates nogc myAssert(cond, mayThrow()); // violates nothrow --- Iain.On 8/1/18 3:59 AM, Shachar Shemesh wrote:import std.string; alias Dg = string delegate() nogc nothrow; void myAssert(bool cond, scope Dg[1] msg_dg ...) nogc nothrow { import core.stdc.stdio; if (!cond) { string msg = msg_dg[0](); printf("%*s\n", msg.length, msg.ptr); } } void main() nogc { string msg = "Hello"; myAssert(true, msg); // <- errors on this line } It errors out: complains it needs to allocate main's frame on the GC, but main is nogc. The same happens if I move the scope to the alias.Thank you! Finally! Let me just state, for the record, that having *yet another* syntax special case is just appalling.The lazy variadic thing is a distinction between specifying variadic lazy parameters and a lazy variadic array. The distinction is so miniscule, but necessary to have a disambiguous syntax. But I had actually thought for a while, that you could simply specify a delegate, and it would be treated as a lazy parameter, which would probably solve your problem. I really think this syntax should be available.With that said, I was hoping that specifying it explicitly as a delegate would allow me to scope it. Apparently, that doesn't work :-(I guess you mean you can't scope the delegates? I'm surprised if that doesn't work. -Steve
Aug 01 2018
On Wednesday, 1 August 2018 at 20:32:11 UTC, Iain Buclaw wrote:On 1 August 2018 at 18:52, Shachar Shemesh via Digitalmars-d <digitalmars-d puremagic.com> wrote:Isn't this https://issues.dlang.org/show_bug.cgi?id=12647?[...]My first thought was to have a look at enforce(), but on closer observation it is neither nogc or nothrow. Maybe you should raise a bug report? It's certainly worth an attempt to bridge these two features together. I think it makes sense enough that lazy parameters should infer attributes from the function, and that it should be an error to pass a parameter that does not meet those constraints. i.e: --- // Signatures. void myAssert(bool cond, lazy string msg) nogc nothrow; string mayAlloc() nothrow; string mayThrow() nogc; // Code myAssert(cond, mayAlloc()); // violates nogc myAssert(cond, mayThrow()); // violates nothrow --- Iain.
Aug 02 2018
On 2 August 2018 at 16:14, Seb via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Wednesday, 1 August 2018 at 20:32:11 UTC, Iain Buclaw wrote:Seems so, good to know. I'll bookmark it for when I get time to do other things. Iain.On 1 August 2018 at 18:52, Shachar Shemesh via Digitalmars-d <digitalmars-d puremagic.com> wrote:Isn't this https://issues.dlang.org/show_bug.cgi?id=12647?[...]My first thought was to have a look at enforce(), but on closer observation it is neither nogc or nothrow. Maybe you should raise a bug report? It's certainly worth an attempt to bridge these two features together. I think it makes sense enough that lazy parameters should infer attributes from the function, and that it should be an error to pass a parameter that does not meet those constraints. i.e: --- // Signatures. void myAssert(bool cond, lazy string msg) nogc nothrow; string mayAlloc() nothrow; string mayThrow() nogc; // Code myAssert(cond, mayAlloc()); // violates nogc myAssert(cond, mayThrow()); // violates nothrow --- Iain.
Aug 03 2018
On 01/08/18 17:13, Steven Schveighoffer wrote:The lazy variadic thing is a distinction between specifying variadic lazy parameters and a lazy variadic array.I have now read that sentence 4 times, and I still have no idea what it means. Can you give examples of both? Shachar
Aug 01 2018
On 8/1/18 10:14 PM, Shachar Shemesh wrote:On 01/08/18 17:13, Steven Schveighoffer wrote:import std.stdio; // lazy variadic array void foo(lazy int[] arr...) { writeln(arr[0]); writeln(arr[1]); writeln(arr[2]); } // variadic lazy paramters void bar(int delegate()[] items...) { writeln(items[0]()); writeln(items[1]()); writeln(items[2]()); } int param(int x) { writeln("param ", x); return x; } void main() { foo(param(0), param(1), param(2)); bar(param(0), param(1), param(2)); } output: param 0 param 1 param 2 0 param 0 param 1 param 2 1 param 0 param 1 param 2 2 param 0 0 param 1 1 param 2 2 So in the first case, the ENTIRE array is evaluated lazily, and then an element selected. In the second case, each item is evaluated when used. -SteveThe lazy variadic thing is a distinction between specifying variadic lazy parameters and a lazy variadic array.I have now read that sentence 4 times, and I still have no idea what it means. Can you give examples of both?
Aug 02 2018
On 2018-08-02 13:33, Steven Schveighoffer wrote:// variadic lazy paramters void bar(int delegate()[] items...) { writeln(items[0]()); writeln(items[1]()); writeln(items[2]()); }I'm surprised that this doesn't need to be called with a delegate syntax, i.e. bar({ return 0; }); -- /Jacob Carlborg
Aug 04 2018
On 8/4/18 3:07 PM, Jacob Carlborg wrote:On 2018-08-02 13:33, Steven Schveighoffer wrote:See one of the earlier posts, it's a lazy variadic function. A little-known D feature. -Steve// variadic lazy paramters void bar(int delegate()[] items...) { writeln(items[0]()); writeln(items[1]()); writeln(items[2]()); }I'm surprised that this doesn't need to be called with a delegate syntax, i.e. bar({ return 0; });
Aug 04 2018
On 2018-08-02 13:33, Steven Schveighoffer wrote:// variadic lazy paramters void bar(int delegate()[] items...) { writeln(items[0]()); writeln(items[1]()); writeln(items[2]()); }Adding nogc to this example works. -- /Jacob Carlborg
Aug 04 2018
On Tuesday, 31 July 2018 at 20:03:39 UTC, ag0aep6g wrote:Looks like you can do it with a "lazy variadic function" [1],Interesting, thanks. I've made a pull to add a See Also link about this to the Lazy Parameters docs: https://github.com/dlang/dlang.org/pull/2439
Aug 05 2018
On 2018-07-31 09:17, Shachar Shemesh wrote:I'm trying to figure out what's the signature of the built-in assert. It does not seem that I can define a similar function myself. First attempt: void myAssert(bool cond, string msg) nogc nothrow; No, because msg gets evaluated unconditionally. void myAssert(bool cond, lazy string msg) nogc nothrow; test.d(8): Error: nogc function test.myAssert cannot call non- nogc delegate msg void myAssert(bool cond, lazy string msg nogc nothrow ) nogc nothrow; test.d(4): Error: found when expecting ) test.d(4): Error: semicolon expected following function declaration test.d(4): Error: no identifier for declarator nogc test.d(4): Error: declaration expected, not ) test.d(9): Error: unrecognized declaration Templates to the rescue!!! void myAssert(STR)(bool cond, lazy STR msg ); test.d(14): Error: nogc function D main cannot call non- nogc function test.myAssert!string.myAssertBased on what Steven said and what I found in the spec, this seems to work with the current language [1]: extern (C) int printf(in char*, ...) nogc nothrow; void myAssert(bool cond, string delegate() nogc nothrow[1] msg ...) nogc nothrow { msg[0](); } string param() nogc nothrow { printf("bar\n"); return "foo"; } void main() nogc nothrow { myAssert(false, param()); } This prints "bar". But if the delegate is not called, then nothing is printed. The signature of "myAssert" is bit ugly and not straightforward to understand, but it works. I think it should be possible to specify attributes for lazy parameters or they should be automatically inferred. Is there an issue for this reported? [1] https://run.dlang.io/is/g4Rm1w -- /Jacob Carlborg
Aug 04 2018