June 18, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra Attachments:
| 2013/6/18 monarch_dodra <monarchdodra@gmail.com> > On Saturday, 8 June 2013 at 15:56:47 UTC, deadalnix wrote: > >> On Saturday, 8 June 2013 at 14:52:23 UTC, monarch_dodra wrote: >> >> Sound like a nice idiom. Why is the first set of () needed ? Can we change the grammar to remove them ? >> > > I've been playing around with this idiom some more, and found some pretty serious limitations: > > # Scoped block: > Using a lambda functions creates a new scope. Having a "true" labeled > block, just like static ifs, should not create a new scope. This is > relevant if you want to make sure a constructor or destructor is nothrow, > for example (destructor could be handled via a simple attribute followed by > a colon. eg: > > void foo() > { > nothrow { > Sentinel s; //declare sentinel > } > > code_goes_here > > nothrow: > clean_up_goes_here_code > destructors_are_nothrow > } > > A lambda would not allow these two constructs. > In D, variable declaration with default construction is always nothrow. So, enclosing the declaration of s by nothrow block is unnecessary. For nothrow destruction, you can add following static assert in foo(). static assert(__traits(compiles, ()nothrow{ Sentinel s; }), "Sentinel dtor is not nothrow"); # Purity > Because a lambda needs to access the frame, any function using the lambda > trick can't be made pure: > void foo(T)(T a) @safe > { > (){ > ++a; > }(); > } > Error: pure function 'main.foo' cannot call impure function literal > '__lambda1' > > The workaround is to explicitly pass the arguments, *preferably*, > shadowing them for clarity: > void foo(int a) pure > { > (ref int a){ > ++a; > }(a); > } > This is already *much* less convenient. Imagine if the block needed to > access 3, 5 or even more variabes ! Also, if one of those variables is > declared as "auto", then you bring in the "ref typeof(a) a" ugliness. Just > no. This is a compiler bug, and I recently fixed it in git master. Explicit argument passing does not need anymore. > # Performance > I haven't actually tested this one, but I'd be inclined to think there is > a performance hit for non-release and non-inline builds. inline builds > *may* optimize it away, but I'm not sure... > Inlining should remove performance penalty. Nobody holds the immediately called lambda, so it should be treated as a 'scope delegate'. For that, we would need to add a section in language spec to support it. > ---------------- > So my conclusion is that the lambda tric is a partial workaround. We'd need real support for being able to have specific qualification inside bodies. > I don't think so. We can sufficiently use lambda for the "attribute block". Kenji Hara |
June 18, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenji Hara | On Tuesday, 18 June 2013 at 07:58:06 UTC, Kenji Hara wrote: > In D, variable declaration with default construction is always nothrow. > So, enclosing the declaration of s by nothrow block is unnecessary. Well, what about construction with args... > For nothrow destruction, you can add following static assert in foo(). > > static assert(__traits(compiles, ()nothrow{ Sentinel s; }), "Sentinel > dtor is not nothrow"); Right. Good point. > This is a compiler bug, and I recently fixed it in git master. Explicit > argument passing does not need anymore. Cool, thanks. > Inlining should remove performance penalty. Nobody holds the immediately > called lambda, so it should be treated as a 'scope delegate'. For that, we > would need to add a section in language spec to support it. Alright. >> ---------------- >> So my conclusion is that the lambda tric is a partial workaround. We'd >> need real support for being able to have specific qualification inside >> bodies. >> > > I don't think so. We can sufficiently use lambda for the "attribute block". > > Kenji Hara Maybe you are right. I will keep using it for now. |
June 18, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Saturday, 8 June 2013 at 14:57:17 UTC, monarch_dodra wrote:
> My beef though is that the syntax is a bit opaque, and not really idiomatic. It looks more like a hacker's trick than a real language feature. It's not something you'd do "naturally". At least, I know a beginner may not feal comfortable with this.
>
> Given that users are now actually doing this, that we have proof it works and is a useful feature, shouldn't we push to have actual blocks with attributes in the language?
>
> I think we should... Thoughts?
Here's my go at cleaning up the syntax a bit:
----
auto block(string attr)() {
static struct Blk {
mixin(q{
void opBinary(string op:"in", T)(T dg) } ~ attr ~ q{
if (is(typeof(() } ~ attr ~ q{ { dg(); }))) {
dg();
}
void opBinary(string op:"in", T)(T dg) if (!is(typeof(() } ~ attr ~ ` { dg(); }))) {
static assert(false, "Provided delegate is not " ~ "` ~ attr ~ `");
}
`);
}
return Blk();
}
void main() {
// Works
block!"nothrow" in {
// Doesn't throw
};
// Fails
block!"nothrow" in {
throw new Exception("");
};
}
----
Downsides are the required semicolon (needed for your method too) and abuse of operator overloading.
|
June 19, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Tuesday, 18 June 2013 at 08:10:24 UTC, monarch_dodra wrote:
>> Inlining should remove performance penalty. Nobody holds the immediately
>> called lambda, so it should be treated as a 'scope delegate'. For that, we
>> would need to add a section in language spec to support it.
>
> Alright.
I did some benching, and they aren't getting inline (well... I don't *think* they are): Code with an inline lambda call is definitely slower (in my case, with no args passed).
My tests are somewhat synthetic, (I'm testing a rather short function with a lambda) but the overall slowdown is quite noticeable. I don't worry about it much, but I guess these could scale in the grand scheme of things, and is a bit vexing when all you wanted to was mark something as trusted :/
Shouldn't an inlined lambda call *always* be... inlined? I really don't see a reason not to do so, but I'm outside my field of competence at that point.
|
June 30, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenji Hara | On 06/18/2013 09:57 AM, Kenji Hara wrote:
>
> # Purity
> Because a lambda needs to access the frame, any function using the
> lambda trick can't be made pure:
> void foo(T)(T a) @safe
> {
> (){
> ++a;
> }();
> }
> Error: pure function 'main.foo' cannot call impure function literal
> '__lambda1'
>
> The workaround is to explicitly pass the arguments, *preferably*,
> shadowing them for clarity:
> void foo(int a) pure
> {
> (ref int a){
> ++a;
> }(a);
> }
> This is already *much* less convenient. Imagine if the block needed
> to access 3, 5 or even more variabes ! Also, if one of those
> variables is declared as "auto", then you bring in the "ref
> typeof(a) a" ugliness. Just no.
>
>
> This is a compiler bug, and I recently fixed it in git master. Explicit
> argument passing does not need anymore.
Great. Does the fix also introduce the 'immutable' storage class for function literals for the case where a strongly pure literal is wanted?
|
July 01, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Sunday, 30 June 2013 at 20:29:07 UTC, Timon Gehr wrote:
>> This is a compiler bug, and I recently fixed it in git master. Explicit
>> argument passing does not need anymore.
>
> Great. Does the fix also introduce the 'immutable' storage class for function literals for the case where a strongly pure literal is wanted?
You may want to discuss that issue with Andrei. We had a discussion at DConf about this.
|
August 18, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenji Hara | On Tuesday, 18 June 2013 at 07:58:06 UTC, Kenji Hara wrote:
> Inlining should remove performance penalty. Nobody holds the immediately
> called lambda, so it should be treated as a 'scope delegate'. For that, we
> would need to add a section in language spec to support it.
Kenji:
I've been doing some benchmarks recently: Using an "inlined lambda" seems to really kill performance, both with or without "-inline" (tested with both dmd and gdc).
However, using a named function, and then immediately calling it, there is 0 performance penalty (both w/ and w/o -inline).
Is this a bug? Can it be fixed? Should I file and ER?
|
August 19, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra Attachments:
| 2013/8/18 monarch_dodra <monarchdodra@gmail.com> > On Tuesday, 18 June 2013 at 07:58:06 UTC, Kenji Hara wrote: > >> Inlining should remove performance penalty. Nobody holds the immediately called lambda, so it should be treated as a 'scope delegate'. For that, we would need to add a section in language spec to support it. >> > > Kenji: > > I've been doing some benchmarks recently: Using an "inlined lambda" seems to really kill performance, both with or without "-inline" (tested with both dmd and gdc). > > However, using a named function, and then immediately calling it, there is 0 performance penalty (both w/ and w/o -inline). > > Is this a bug? Can it be fixed? Should I file and ER? > I opened a new bugzilla issue: http://d.puremagic.com/issues/show_bug.cgi?id=10848 And start working for the compiler and doc fix: https://github.com/D-Programming-Language/dlang.org/pull/372 https://github.com/D-Programming-Language/dmd/pull/2483 Kenji Hara |
August 19, 2013 Re: blocks with attributes vs inlined lambda | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenji Hara | On Monday, 19 August 2013 at 02:33:43 UTC, Kenji Hara wrote:
> 2013/8/18 monarch_dodra <monarchdodra@gmail.com>
>
>> On Tuesday, 18 June 2013 at 07:58:06 UTC, Kenji Hara wrote:
>>
>>> Inlining should remove performance penalty. Nobody holds the immediately
>>> called lambda, so it should be treated as a 'scope delegate'. For that, we
>>> would need to add a section in language spec to support it.
>>>
>>
>> Kenji:
>>
>> I've been doing some benchmarks recently: Using an "inlined lambda" seems
>> to really kill performance, both with or without "-inline" (tested with
>> both dmd and gdc).
>>
>> However, using a named function, and then immediately calling it, there is
>> 0 performance penalty (both w/ and w/o -inline).
>>
>> Is this a bug? Can it be fixed? Should I file and ER?
>>
>
> I opened a new bugzilla issue:
> http://d.puremagic.com/issues/show_bug.cgi?id=10848
>
> And start working for the compiler and doc fix:
> https://github.com/D-Programming-Language/dlang.org/pull/372
> https://github.com/D-Programming-Language/dmd/pull/2483
>
> Kenji Hara
As always, thank you *very* much.
|
Copyright © 1999-2021 by the D Language Foundation