Jump to page: 1 2
Thread overview
Local functions
Mar 27, 2003
Matthew Wilson
Mar 27, 2003
Walter
Mar 27, 2003
Matthew Wilson
Mar 27, 2003
Matthew Wilson
Mar 27, 2003
Walter
Mar 27, 2003
Matthew Wilson
Mar 28, 2003
Walter
Mar 28, 2003
Matthew Wilson
Mar 27, 2003
Matthew Wilson
Mar 28, 2003
Mark T
Mar 28, 2003
Matthew Wilson
Mar 29, 2003
Burton Radons
Mar 29, 2003
Matthew Wilson
March 27, 2003
Just trimmed down the implementation of a function, in which I'd had to duplicate similar behaviour in multiple places to achieve optimal performance, by using a local function.

Totally love it!




March 27, 2003
"Matthew Wilson" <dmd@synesis.com.au> wrote in message news:b5uk7n$16tj$1@digitaldaemon.com...
> Just trimmed down the implementation of a function, in which I'd had to duplicate similar behaviour in multiple places to achieve optimal performance, by using a local function.
>
> Totally love it!

Local functions are something we've all learned well to live without in C/C++, and have developed all kinds of idioms and kludges to compensate for it. The neat thing is when one discovers that local functions are the natural solution, and those idioms and kludges are not!


March 27, 2003
Well it's another of those things that has me much more convinced than I was last year that D has a real commercial future.

Now, if we can just sort out this nonsense about equality and identity ...


"Walter" <walter@digitalmars.com> wrote in message news:b5vmgd$2a17$1@digitaldaemon.com...
>
> "Matthew Wilson" <dmd@synesis.com.au> wrote in message news:b5uk7n$16tj$1@digitaldaemon.com...
> > Just trimmed down the implementation of a function, in which I'd had to duplicate similar behaviour in multiple places to achieve optimal performance, by using a local function.
> >
> > Totally love it!
>
> Local functions are something we've all learned well to live without in C/C++, and have developed all kinds of idioms and kludges to compensate
for
> it. The neat thing is when one discovers that local functions are the natural solution, and those idioms and kludges are not!
>
>


March 27, 2003
"Matthew Wilson" <dmd@synesis.com.au> escribió en el mensaje
news:b5uk7n$16tj$1@digitaldaemon.com...
| Just trimmed down the implementation of a function, in which I'd had to
| duplicate similar behaviour in multiple places to achieve optimal
| performance, by using a local function.
|
| Totally love it!
|
|
|
|

This might sound dumb, but what exactly is a local function? A nested function? A private function? Un-dumb me, please :D

————————————————————————— Carlos Santander


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.465 / Virus Database: 263 - Release Date: 2003-03-25


March 27, 2003
Walter and I have been faffing around with some D library performance stuff for an article I'm writing for June's WDM, contrasting C# performance with C, C++, D and Java.

I found that the performance of string.split() was preposterously bad, and wrote two much faster, and more flexible, versions

  char[][] tokenise(char[] source, char delimiter, bit bElideBlanks, bit
bZeroTerminate); // character delimiter, e.g. ';'
  char[][] tokenise(char[] source, char[] delimiter, bit bElideBlanks, bit
bZeroTerminate); // string delimiter, e.g. "\r\n"

Walter then took up the gauntlet and fixed up string.split() such that it
performed faster for character delimiters than my tokenise method. (The
string delimiter of tokenise() calls string.split() and then trims the
blanks in situ if requested. Hence string.split() is slightly better
performing than tokenise() for string delimiters, albeit that the difference
is very slight.)

In turn, I've addressed some issues in my implementation and made tokenise() for char delimiters faster again. The ball is currently in Walter's court, but I'm having to seal the article results today, so whatever happens I've won in print! (Don't worry, this nonsense contest won't be featuring outside this forum ;)

Anyway, one of the ways in which I increased the speed of the original version of tokenise() was to split out the loops for the bElideBlanks = true and bElideBlanks = false. Consider the implementation

char[][] tokenise(char[] source, char delimiter, bit bElideBlanks, bit
bZeroTerminate)
{
 int   i;
 int   cDelimiters = 128;
 char[][] tokens  = new char[][cDelimiters];
 int   start;
 int   begin;
 int   cTokens;

 if(bElideBlanks)
 {
  for(start = 0, begin = 0, cTokens = 0; begin < source.length; ++begin)
  {
   if(source[begin] == delimiter)
   {
    if(start < begin)
    {
     if(!(cTokens < tokens.length))
     {
      tokens.length = tokens.length * 2;
     }

     tokens[cTokens++] = source[start .. begin];
    }

    start = begin + 1;
   }
  }

  if(start < begin)
  {
   if(!(cTokens < tokens.length))
   {
    tokens.length = tokens.length * 2;
   }

   tokens[cTokens++] = source[start .. begin];
  }
 }
 else
 {
  for(start = 0, begin = 0, cTokens = 0; begin < source.length; ++begin)
  {
   if(source[begin] == delimiter)
   {
    if(!(cTokens < tokens.length))
    {
     tokens.length = tokens.length * 2;
    }

    tokens[cTokens++] = source[start .. begin];

    start = begin + 1;
   }
  }

  if(!(cTokens < tokens.length))
  {
   tokens.length = tokens.length * 2;
  }

  tokens[cTokens++] = source[start .. begin];
 }

 tokens.length = cTokens;

 if(bZeroTerminate)
 {
  for(i = 0; i < tokens.length; ++i)
  {
   tokens[i] ~= (char)0;
  }
 }

 return tokens;
}

char[][] tokenize(char[] source, char delimiter, bit bElideBlanks, bit
bZeroTerminate)
{
 return tokenise(source, delimiter, bElideBlanks, bZeroTerminate);
}

As you can see, there's a lot of duplicated code, which is always something that is to be avoided where possible. All that

  if(!(cTokens < tokens.length))
  {
   tokens.length = tokens.length * 2;
  }

is just asking for bugs to creep in. But by creating a local function ensure_length() I can trim the function length, and even more importantly ensure that the array-growing algorithm is managed in one place. The whole function was thus rewritten:

char[][] tokenise(char[] source, char delimiter, bit bElideBlanks, bit
bZeroTerminate)
{
 int   i;
 int   cDelimiters = 128;
 char[][] tokens  = new char[][cDelimiters];
 int   start;
 int   begin;
 int   cTokens;

 /// Ensures that the tokens array is big enough  *** Carlos, this is the
local function ***
 void ensure_length()
 {
  if(!(cTokens < tokens.length))
  {
   tokens.length = tokens.length * 2;
  }
 }

 if(bElideBlanks)
 {
  for(start = 0, begin = 0, cTokens = 0; begin < source.length; ++begin)
  {
   if(source[begin] == delimiter)
   {
    if(start < begin)
    {
     ensure_length();

     tokens[cTokens++] = source[start .. begin];
    }

    start = begin + 1;
   }
  }

  if(start < begin)
  {
   ensure_length();

   tokens[cTokens++] = source[start .. begin];
  }
 }
 else
 {
  for(start = 0, begin = 0, cTokens = 0; begin < source.length; ++begin)
  {
   if(source[begin] == delimiter)
   {
    ensure_length();

    tokens[cTokens++] = source[start .. begin];

    start = begin + 1;
   }
  }

  ensure_length();

  tokens[cTokens++] = source[start .. begin];
 }

 tokens.length = cTokens;

 if(bZeroTerminate)
 {
  for(i = 0; i < tokens.length; ++i)
  {
   tokens[i] ~= (char)0;
  }
 }

 return tokens;
}

There's still scope for more local functions, with

    tokens[cTokens++] = source[start .. begin];

but I simply haven't got to that yet. I probably will before I submit it to Walter for Phobosisation.

Hope that helps. :)

Matthew



"Carlos Santander B." <carlos8294@msn.com> wrote in message news:b5vp1o$2cad$1@digitaldaemon.com...
> "Matthew Wilson" <dmd@synesis.com.au> escribió en el mensaje
> news:b5uk7n$16tj$1@digitaldaemon.com...
> | Just trimmed down the implementation of a function, in which I'd had to
> | duplicate similar behaviour in multiple places to achieve optimal
> | performance, by using a local function.
> |
> | Totally love it!
> |
> |
> |
> |
>
> This might sound dumb, but what exactly is a local function? A nested function? A private function? Un-dumb me, please :D
>
> -------------------------
> Carlos Santander
>
>
> ---
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.465 / Virus Database: 263 - Release Date: 2003-03-25
>
>


March 27, 2003
"Matthew Wilson" <dmd@synesis.com.au> escribió en el mensaje
news:b5vr97$2e7s$1@digitaldaemon.com...
| ...
|  /// Ensures that the tokens array is big enough  *** Carlos, this is the
| local function ***
|  void ensure_length()
|  {
|   if(!(cTokens < tokens.length))
|   {
|    tokens.length = tokens.length * 2;
|   }
|  }
| ...
| Hope that helps. :)
|
| Matthew
|

Well, that was obviously much more information than I was asking, but yes,
it helped. Thanks.
Of course, you could've only said "local functions=nested functions"... lol

————————————————————————— Carlos Santander


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.465 / Virus Database: 263 - Release Date: 2003-03-25


March 27, 2003
"Carlos Santander B." <carlos8294@msn.com> wrote in message news:b5vsa9$2f6c$1@digitaldaemon.com...
> Well, that was obviously much more information than I was asking, but yes,
> it helped. Thanks.
> Of course, you could've only said "local functions=nested functions"...
lol

True, but it is a nice example of what they are good for!


March 27, 2003
"Walter" <walter@digitalmars.com> escribió en el mensaje
news:b5vsn3$2fgb$4@digitaldaemon.com...
|
| "Carlos Santander B." <carlos8294@msn.com> wrote in message
| news:b5vsa9$2f6c$1@digitaldaemon.com...
| > Well, that was obviously much more information than I was asking, but
yes,
| > it helped. Thanks.
| > Of course, you could've only said "local functions=nested functions"...
| lol
|
| True, but it is a nice example of what they are good for!
|
|

Yes, it is.

————————————————————————— Carlos Santander


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.465 / Virus Database: 263 - Release Date: 2003-03-25


March 27, 2003
Aye

Maybe we'll slip that into some documentary form in the future ... ?

"Walter" <walter@digitalmars.com> wrote in message news:b5vsn3$2fgb$4@digitaldaemon.com...
>
> "Carlos Santander B." <carlos8294@msn.com> wrote in message news:b5vsa9$2f6c$1@digitaldaemon.com...
> > Well, that was obviously much more information than I was asking, but
yes,
> > it helped. Thanks.
> > Of course, you could've only said "local functions=nested functions"...
> lol
>
> True, but it is a nice example of what they are good for!
>
>


March 27, 2003
I'm not known for my terseness. It gets me in all kinds of trouble with my publishers. "Less is more!" they cry. "Phooey! More is more!" I cry (to myself, while I duly cut away at my lovely text)

In any case, you're more than welcome.

:)

"Carlos Santander B." <carlos8294@msn.com> wrote in message news:b5vsa9$2f6c$1@digitaldaemon.com...
> "Matthew Wilson" <dmd@synesis.com.au> escribió en el mensaje
> news:b5vr97$2e7s$1@digitaldaemon.com...
> | ...
> |  /// Ensures that the tokens array is big enough  *** Carlos, this is
the
> | local function ***
> |  void ensure_length()
> |  {
> |   if(!(cTokens < tokens.length))
> |   {
> |    tokens.length = tokens.length * 2;
> |   }
> |  }
> | ...
> | Hope that helps. :)
> |
> | Matthew
> |
>
> Well, that was obviously much more information than I was asking, but yes,
> it helped. Thanks.
> Of course, you could've only said "local functions=nested functions"...
lol
>
> -------------------------
> Carlos Santander
>
>
> ---
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.465 / Virus Database: 263 - Release Date: 2003-03-25
>
>


« First   ‹ Prev
1 2