How would you do this in D?
Daniel Gibson
metalcaedes at gmail.com
Tue May 10 17:56:53 PDT 2011
Am 11.05.2011 02:32, schrieb Jose Armando Garcia:
> Hey guys,
>
> I am trying to create a function that return true or executes
> "something" the n-th time it is called from a specific call site. How
> would you do that in D? In C we can do that with the help of
> pre-processor macros. E.g.:
>
> ---
> #include <assert.h>
>
> #define EVERY(N, ACTION) { static int counter = 0; if(++counter > (N))
> counter -= (N); if(counter == 1) (ACTION); }
>
> int main()
> {
> int i = 0;
> int j = 0;
> while(i < 10)
> {
> EVERY(10, ++j);
> EVERY(2, ++i);
> }
> assert(j == 2);
> assert(i == 10);
> }
> ---
>
> In D, I hacked the following implementation. I don't like this
> implementation for a log of reason... Am I missing some D feature? Can
> someone do better?
>
> ---
> int[string] map;
>
> bool every(string file = __FILE__, int line = __LINE__)(int time)
> {
> // assume file ~ "+" ~ to!string(line) is unique
> // assumption could be removed by using a struct
> string key = file ~ "+" ~ to!string(line);
>
> map[key] += 1;
> if(map[key] > time) map[key] -= time;
>
> return map[key] == 1;
> }
>
> unittest
> {
> auto i = 0;
> auto j = 0;
> while(i < 10)
> {
> if(every(10)) ++j;
> if(every(2)) ++i;
> }
> assert(j == 2);
> assert(i == 10);
> }
>
> void main() {}
> ---
>
> Thanks!
> -Jose
1. For ACTION you could use a delegate/lambda
2. Using a map is an ugly hack IMHO. IMHO it's not necessary, because
the code generated by the template will be unique if __FILE__ and
__LINE__ are unique (as you assume), so you could use a static int like
in C.
However, it's probably smarter and more clean to have struct (or maybe
class) containing the counter, the delegate and the threshold (10 for
every 10 etc) and a method incrementing the counter and invoking the
delegate.
The code isn't as short as the C version, but the implementation is more
clean IMHO: http://pastebin.com/XVSnALbq
There may be a more clever template-trick, however.
Cheers,
- Daniel
More information about the Digitalmars-d
mailing list