Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Shachar Shemesh via Digitalmars-d
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


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread rikki cattermole via Digitalmars-d

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.


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Mike Franklin via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Shachar Shemesh via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Guillaume Boucher via Digitalmars-d

On Tuesday, 31 July 2018 at 07:49:40 UTC, Shachar Shemesh wrote:

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


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 
(http://groovy-lang.org/semantics.html#_power_assertion):


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.


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Jacob Carlborg via Digitalmars-d

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.myAssert


It 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


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Seb via Digitalmars-d

On Tuesday, 31 July 2018 at 07:49:40 UTC, Shachar Shemesh wrote:

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


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).


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Steven Schveighoffer via Digitalmars-d

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 msg


Hm... 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


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread ag0aep6g via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-08-01 Thread Shachar Shemesh via Digitalmars-d

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




Re: Is there any hope for "lazy" and @nogc?

2018-08-01 Thread Steven Schveighoffer via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-08-01 Thread Shachar Shemesh via Digitalmars-d

On 01/08/18 17:13, Steven Schveighoffer wrote:

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




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.


Re: Is there any hope for "lazy" and @nogc?

2018-08-01 Thread Iain Buclaw via Digitalmars-d
On 1 August 2018 at 18:52, Shachar Shemesh via Digitalmars-d
 wrote:
> On 01/08/18 17:13, Steven Schveighoffer wrote:
>>
>> 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
>
>
>
>
> 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.

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.


Re: Is there any hope for "lazy" and @nogc?

2018-08-01 Thread Shachar Shemesh via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-08-02 Thread Steven Schveighoffer via Digitalmars-d

On 8/1/18 10:14 PM, Shachar Shemesh wrote:

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?


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.


-Steve


Re: Is there any hope for "lazy" and @nogc?

2018-08-02 Thread Seb via Digitalmars-d

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 
 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.


Isn't this https://issues.dlang.org/show_bug.cgi?id=12647?


Re: Is there any hope for "lazy" and @nogc?

2018-08-03 Thread Iain Buclaw via Digitalmars-d
On 2 August 2018 at 16:14, Seb via Digitalmars-d
 wrote:
> 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
>>  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.
>
>
> Isn't this https://issues.dlang.org/show_bug.cgi?id=12647?

Seems so, good to know.  I'll bookmark it for when I get time to do
other things.

Iain.


Re: Is there any hope for "lazy" and @nogc?

2018-08-04 Thread Jacob Carlborg via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-08-04 Thread Jacob Carlborg via Digitalmars-d

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


Re: Is there any hope for "lazy" and @nogc?

2018-08-04 Thread Steven Schveighoffer via Digitalmars-d

On 8/4/18 3:07 PM, Jacob Carlborg wrote:

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; });



See one of the earlier posts, it's a lazy variadic function. A 
little-known D feature.


-Steve


Re: Is there any hope for "lazy" and @nogc?

2018-08-04 Thread Jacob Carlborg via Digitalmars-d

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.myAssert



Based 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


Re: Is there any hope for "lazy" and @nogc?

2018-08-05 Thread Nick Treleaven via Digitalmars-d

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