Thread overview | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 13, 2012 The One-Letter Nested Function - a sample article for some kind of D "gems" website | ||||
---|---|---|---|---|
| ||||
I wrote this article because I felt like helping other people coming to D, but I'm not sure where the appropriate place to make such a contribution is. Maybe a "Learning Articles" or an "Idioms" section. The One-Letter Nested Function As a programmer new to D I wanted to share an idiom I've been using. This article will share two cases in which I've found the "one-letter nested function" to come in very handy. The following function has a lot of ugly "cast(" code. void setRandomColorPair( ref ColorPair cp ) { import std.random; cp.foreground = Color( cast(ubyte) uniform(40,200), cast(ubyte) uniform(50,100), cast(ubyte) uniform(150, 250) ); cp.background = Color( cast(ubyte) uniform(40,200), cast(ubyte) uniform(50,100), cast(ubyte) uniform(200, 250) ); } But with the one-letter nested function, the above became: void setRandomColorPair( ref ColorPair cp ) { import std.random; ubyte u(int a, int b) { return cast(ubyte) uniform(a,b); } cp.foreground = Color( u(40,200), u(50,100), u(150, 250) ); cp.background = Color( u(40,200), u(50,100), u(200, 250) ); } It was a mild gain, but it really started to add up when I was assigning to more than just two variables. The next example is for C programmers. Suppose you're faced with translating this code written in C: void print_init_flags(int flags) { #define PFLAG(a) if( flags & INIT_##a ) printf(#a " ") PFLAG(FLAC); PFLAG(MOD); PFLAG(MP3); PFLAG(OGG); if(!flags) printf("None"); printf("\n"); } That #define macro is actually quite efficient, and since D doesn't have literal macros it looks like the D replacement could get pretty wordy, since we're going to need string mix-ins. But D *does* have nested functions. Look: void printInitFlags( int flags ) { string w(string f) { return `if( flags & INIT_`~f~` ) write("MIX_INIT_`~f~` ");`; } mixin( w("FLAC") ); mixin( w("MOD") ); mixin( w("MP3") ); mixin( w("OGG") ); if(!flags) write ("None"); writeln(); } This is, I think, one of the rare cases where the C code is actually more concise than the translated D code, but when I tried the one-letter nested function idiom, it became a moot point. |
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind of D "gems" website | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zach the Mystic | With 2.058 the single-letter function can become: auto u = (int a, int b) => cast(ubyte)uniform(a, b); It's not much of savings in typing. The only problem is I can't seem to make it static: static u = (int a, int b) => cast(ubyte)uniform(a, b); Error: non-constant nested delegate literal expression __lambda1 It would be better if you didn't have to specify the argument types. I think bear asked for templated lambdas, so this could eventually become: auto u = (a, b) => cast(ubyte)uniform(a, b); Which would make 'u' a template. I'm not sure what the exact syntax was that was requested though. |
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind of D "gems" website | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 2/13/12 2:43 PM, Andrej Mitrovic wrote:
> auto u = (a, b) => cast(ubyte)uniform(a, b);
>
> Which would make 'u' a template. I'm not sure what the exact syntax
> was that was requested though.
This could never work without major changes to the language, because 'u' cannot be assigned a type.
David
|
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind of | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zach the Mystic | Zach the Mystic: > void setRandomColorPair( ref ColorPair cp ) > { > import std.random; > ubyte u(int a, int b) { return cast(ubyte) uniform(a,b); } Where possible it's good to add "static" to nested functions: static ubyte u(in int a, in int b) pure nothrow { return cast(ubyte) uniform(a,b); } ----------------- Andrej Mitrovic: > It would be better if you didn't have to specify the argument types. I think bear asked for templated lambdas, so this could eventually become: Some related requests (one and half of them is by me): http://d.puremagic.com/issues/show_bug.cgi?id=7357 http://d.puremagic.com/issues/show_bug.cgi?id=7308 http://d.puremagic.com/issues/show_bug.cgi?id=7176 Bye, bearophile |
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind of D "gems" website | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On 2/13/12, David Nadlinger <see@klickverbot.at> wrote:
> This could never work without major changes to the language, because 'u' cannot be assigned a type.
Yeah, the syntax is wrong. I found bear's post and the syntax:
alias (x => x ^^ 2) sqrTemplate;
So it would be:
alias ((a, b) => cast(ubyte)uniform(a, b)) u;
|
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind of D "gems" website | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 13/02/2012 14:21, Andrej Mitrovic wrote:
> On 2/13/12, David Nadlinger<see@klickverbot.at> wrote:
>> This could never work without major changes to the language, because 'u'
>> cannot be assigned a type.
>
> Yeah, the syntax is wrong. I found bear's post and the syntax:
>
> alias (x => x ^^ 2) sqrTemplate;
>
> So it would be:
> alias ((a, b) => cast(ubyte)uniform(a, b)) u;
Here 'alias name = expression' syntax helps shed brackets:
alias u = (a, b) => cast(ubyte)uniform(a, b);
That looks nice IMO.
|
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind of | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 2/13/12 9:14 AM, bearophile wrote:
>
> Where possible it's good to add "static" to nested functions:
>
> static ubyte u(in int a, in int b) pure nothrow { return cast(ubyte) uniform(a,b); }
>
You're right. The only advantage to the way I wrote it is, possibly, it's easier for new people (like myself) to grasp the idea. But I'm pretty sure uniform is NOT a pure function. In fact, generating random numbers is about as far opposite a "pure" function as you can get, right? :-)
|
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kindof D "gems" website | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | "Andrej Mitrovic" <andrej.mitrovich@gmail.com> wrote in message news:mailman.283.1329140648.20196.digitalmars-d@puremagic.com... > The only problem is I can't seem to make it static: > static u = (int a, int b) => cast(ubyte)uniform(a, b); auto u = function (int a, int b) => cast(ubyte)uniform(a, b); Should do it. |
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kind | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zach the Mystic | Zach the Mystic: > But I'm pretty sure uniform is NOT a pure function. In fact, generating random numbers is about as far opposite a "pure" function as you can get, right? :-) Right, and sorry, I didn't see the function contents. If I don't run the D code you have to assume it's wrong code. Regarding pure random generators, I have asked it too: http://d.puremagic.com/issues/show_bug.cgi?id=5249 Bye, bearophile |
February 13, 2012 Re: The One-Letter Nested Function - a sample article for some kindof D "gems" website | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Murphy | On 2/13/12 5:17 PM, Daniel Murphy wrote:
> "Andrej Mitrovic"<andrej.mitrovich@gmail.com> wrote in message
> news:mailman.283.1329140648.20196.digitalmars-d@puremagic.com...
>> The only problem is I can't seem to make it static:
>> static u = (int a, int b) => cast(ubyte)uniform(a, b);
>
> auto u = function (int a, int b) => cast(ubyte)uniform(a, b);
>
> Should do it.
I know it currently isn't, but shouldn't this be inferred as per TDPL anyway?
David
|
Copyright © 1999-2021 by the D Language Foundation