May 15, 2014
On Thursday, 15 May 2014 at 06:52:44 UTC, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Thu, 15 May 2014 05:53:45 +0000
> monarch_dodra via Digitalmars-d-learn
> <digitalmars-d-learn@puremagic.com> wrote:
>
>> As a workaround, I'm sure we could specialize enforce without
>> lazy for built-in types?
>
> No. I don't think that that would work. The problem is that you'd have to be
> able to overload between stuff like "error message" and
> format("error message: %s", foo), because you don't want the first one to be
> lazy, whereas you do want the second one to be lazy.

Oh... right. It's the *second* parameter that's lazy.

Arguably, the compiler should be able too "see" if the argument passed is a value or an expression though, and optimize accordingly.
May 15, 2014
On 5/15/14, 1:31 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Thu, 15 May 2014 01:29:23 +0000
> Kapps via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
>
>> On Wednesday, 14 May 2014 at 23:50:34 UTC, Meta wrote:
>>> On the topic of lazy, why *is* it so slow, exactly? I thought
>>> it was just shorthand for taking a function that evaluates the
>>> expression, and wrapping said expression in that function at
>>> the call site. That is, I thought that:
>>>
>>> int doSomething(lazy int n)
>>> {
>>>      return n();
>>> }
>>>
>>> Was more or less equivalent to:
>>>
>>> int doSomething(int function(int) n)
>>> {
>>>      return n();
>>> }
>>
>> It's more equivalent to:
>>
>> int doSomething(int delegate(int) n)
>> {
>>       return n();
>> }
>>
>> And (I could be very likely wrong here), I believe that it's
>> expensive because it's not scope and possibly requires a closure.
>> Again, very likely may be wrong.
>
> Yeah. It generates a delegate. You even use the value internally as a
> delegate. So, that's definitely part of the problem, though IIRC, there were
> other issues with it. However, I don't remember at the moment. The big one
> IIRC (which may be due to its nature as a delegate) is simply that it can't be
> inlined, and in many cases, you very much what the code to be inlined (enforce
> would be a prime example of that).
>
> enforce(cond, "failure");
>
> really should just translate to something close to
>
> if(!cond) throw new Exception("failure");
>
> but it doesn't do anything close to that.

Isn't there a way in D to just expand:

enforce(cond, "failure");

(or something with a similar syntax) to this, at compile-time:

if(!cond) throw new Exception("failure");

I thought D could do this, so enforce should do this instead of using lazy arguments.
May 15, 2014
On Wed, 14 May 2014 19:50:33 -0400, Meta <jared771@gmail.com> wrote:

> On Wednesday, 14 May 2014 at 22:32:01 UTC, Jonathan M Davis via Digitalmars-d-learn wrote:
>> Yeah, much as Andrei would hate to hear it (enforce was his idea, and he quite
>> likes the idiom), the fact that lazy is so inefficient makes it so that it's
>> arguably bad practice to use it in high performance code. We really need to
>> find a way to make it so that lazy is optimized properly so that we _can_
>> safely use enforce, but for now, it's not a good idea unless the code that
>> you're working on can afford the performance hit.
>>
>> Honestly, in general, I'd avoid most anything which uses lazy (e.g. that's why
>> I'd use explict try-catch blocks rather than use
>> std.exception.assumeWontThrow - like enforce, it's a nice idea, but it's too
>> expensive at this point).
>>
>> - Jonathan M Davis
>
> On the topic of lazy, why *is* it so slow, exactly?

Last time I remember, the issue is that functions with lazy parameters will never be inlined.

-Steve
May 16, 2014
On Thu, 15 May 2014 08:04:59 -0300
Ary Borenszweig via Digitalmars-d-learn
<digitalmars-d-learn@puremagic.com> wrote:

> Isn't there a way in D to just expand:
>
> enforce(cond, "failure");
>
> (or something with a similar syntax) to this, at compile-time:
>
> if(!cond) throw new Exception("failure");
>
> I thought D could do this, so enforce should do this instead of using lazy arguments.

No. enforce is a function, and the only other things that it could be with that syntax would be other callables (e.g. a lambda, delegate, or functor). Mixins are the only constructs that can completely replace themselves with another construct. So, I suppose that you could have a function called enforce that returned a string and be able to do something like

mixin(enforce("cond", `"failure"`));

and you could probably do something similar with a template mixin.

mixin(enforce!(cond, "failure"));

might be possible if both of the template parameters were alias parameters. But there's no way to take one piece of code and completely translate it into another piece of code without mixins. To do that probably would have meant using some kind of macros, or that was specifically avoided in D's design.

And conceptually, using lazy for enforce is a perfect fit. The problem is with the current implementation of lazy.

- Jonathan M Davis
May 16, 2014
On Fri, 16 May 2014 11:36:44 -0400, Jonathan M Davis via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

> On Thu, 15 May 2014 08:04:59 -0300
> Ary Borenszweig via Digitalmars-d-learn
> <digitalmars-d-learn@puremagic.com> wrote:
>
>> Isn't there a way in D to just expand:
>>
>> enforce(cond, "failure");
>>
>> (or something with a similar syntax) to this, at compile-time:
>>
>> if(!cond) throw new Exception("failure");
>>
>> I thought D could do this, so enforce should do this instead of using
>> lazy arguments.
>
> No. enforce is a function, and the only other things that it could be with
> that syntax would be other callables (e.g. a lambda, delegate, or functor).

I think it *could* optimize properly, and that would be an amazing improvement to the compiler, if someone wants to implement that.

Essentially, you need to be able to inline enforce (not a problem since it's a template), and then deduce that the lazy calls can just be moved to where they are used, in this case, only once.

This would make a logging library even better too.

-Steve
May 17, 2014
On Fri, 16 May 2014 11:51:31 -0400
Steven Schveighoffer via Digitalmars-d-learn
<digitalmars-d-learn@puremagic.com> wrote:

> On Fri, 16 May 2014 11:36:44 -0400, Jonathan M Davis via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
>
> > On Thu, 15 May 2014 08:04:59 -0300
> > Ary Borenszweig via Digitalmars-d-learn
> > <digitalmars-d-learn@puremagic.com> wrote:
> >
> >> Isn't there a way in D to just expand:
> >>
> >> enforce(cond, "failure");
> >>
> >> (or something with a similar syntax) to this, at compile-time:
> >>
> >> if(!cond) throw new Exception("failure");
> >>
> >> I thought D could do this, so enforce should do this instead of using lazy arguments.
> >
> > No. enforce is a function, and the only other things that it could
> > be with
> > that syntax would be other callables (e.g. a lambda, delegate, or
> > functor).
>
> I think it *could* optimize properly, and that would be an amazing improvement to the compiler, if someone wants to implement that.
>
> Essentially, you need to be able to inline enforce (not a problem since it's a template), and then deduce that the lazy calls can just be moved to where they are used, in this case, only once.
>
> This would make a logging library even better too.

Sure, the compiler could be improved to optimize enforce such that

    enforce(cond, "failure");

becomes

    if(!cond) throw new Exception("failure");

And I think that that's what needs to be done. However, what I understood the question to be was whether there was a construct in the language that we could use where

    enforce(cond, "failure");

would be automatically converted to

    if(!cond) throw new Exception("failure");

without the compiler having to do optimizations to make it happen. The closest to that would be mixins, but they can't do it with the same syntax. You'd be required to write something more complex to use mixins to do the job.

But I think that the correct solution is to improve the compiler with regards to lazy. The fact that lazy is so slow is a serious problem, and enforce is just one manifestation of it (albeit the worst because of how often it's used).

- Jonathan M Davis
May 17, 2014
On Saturday, 17 May 2014 at 20:06:03 UTC, Jonathan M Davis via Digitalmars-d-learn wrote:
> But I think that the correct solution is to improve the compiler with regards
> to lazy. The fact that lazy is so slow is a serious problem, and enforce is
> just one manifestation of it (albeit the worst because of how often it's
> used).
>
> - Jonathan M Davis

I haven't been bitten by the performance of lazy myself, but I'd +1 that, because of how easy it can make writing code.
1 2 3
Next ›   Last »