Amusing D facts: typesafe variadic arrays are lazy!

Jeremie Pelletier jeremiep at gmail.com
Tue Oct 13 13:48:28 PDT 2009


Andrei Alexandrescu wrote:
> Jeremie Pelletier wrote:
>> Leandro Lucarella wrote:
>>> Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:
>>>> downs wrote:
>>>>> Did you know the following code compiles?
>>>>>
>>>>>> module test;
>>>>>>
>>>>>> import std.stdio;
>>>>>>
>>>>>> void Assert(bool cond, string delegate()[] dgs...) {
>>>>>>  debug if (!cond) {
>>>>>>    string str;
>>>>>>    foreach (dg; dgs) str ~= dg();
>>>>>>    throw new Exception(str);
>>>>>>  }
>>>>>> }
>>>>>>
>>>>>> void main() {
>>>>>>  Assert(false, "O hai thar! ");
>>>>>> }
>>>>>
>>>>> It's true! :)
>>>> Gosh!!! What's happening over here? I even tried this:
>>>>
>>>> import std.stdio;
>>>>
>>>> void Assert(bool cond, string delegate()[] dgs...) {
>>>>     if (!cond) {
>>>>         string str;
>>>>         foreach (dg; dgs) str ~= dg();
>>>>         throw new Exception(str);
>>>>     }
>>>> }
>>>>
>>>> string fun(string a, string b) {
>>>>     writeln("Concatenating...");
>>>>     return a ~ b;
>>>> }
>>>>
>>>> void main() {
>>>>     Assert(true, fun("O hai thar! ", "wyda"));
>>>>     Assert(false, fun("O hai thar! ", "wyda"));
>>>> }
>>>>
>>>> This example only prints "Concatenatning..." once, meaning that fun
>>>> is also lazified!!!
>>>>
>>>> This is very exciting! The fact that this little anomaly hasn't
>>>> caused trouble is a good sign it could actually replace lazy!
>>>
>>> What is the relation between assert and pure/nothrow? Is assert allowed?
>>> I think it should be, since an assert is expressing a very essential
>>> property of the software, it can't happen in a normal flow of the 
>>> program.
>>>
>>> If this is the case, I guess assert should be kept as a language 
>>> construct
>>> so it can be always be used in pure/nothrow functions.
>>>
>>
>> It works for the reason you said, assertions either guard against an 
>> unreachable code path or invalid values. AssertError throwables aren't 
>> meant to be recovered from (as should any Error) so they're perfectly 
>> fine in pure or nothrow contexts.
>>
>> I often use assert(0) to mark unreachable paths, and the compiler 
>> don't warn me that some paths of a function have no return value. For 
>> that reason I also want assert() to stay a compiler intrinsic, 
>> especially since having assert() as a library routine and static 
>> assert() as a compiler feature sounds weird.
>>
>> Jeremie
> 
> I think that's sensible, and thanks all for revealing reasons for assert 
> to stay in the language.
> 
> As far as lazy goes, I think the lazy variadic functions are a 
> compelling feature that renders lazy unnecessary. I plan to put no 
> reference to lazy in TDPL. (Before someone else leaves the group: I just 
> talked to Walter and he approved that.)
> 
> 
> Andrei

I wouldn't mind lazy going away, its something that can be 100% covered 
by delegates and closures, maybe keep lazy as a lazy way of writing a 
delegate?

'lazy int foo' could semantically equivalent to 'scope int delegate() 
foo'. It would get called as {return 1;} and evaluated as foo().

Jeremie



More information about the Digitalmars-d mailing list