The One-Letter Nested Function - a sample article for some kind of D "gems" website

Zach the Mystic reachzachatgooglesmailservice at dot.com
Mon Feb 13 05:19:36 PST 2012


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.


More information about the Digitalmars-d mailing list