Any ideas for lazy evaluation on varaible argument functions?

Christopher Wright dhasenan at gmail.com
Thu Oct 18 20:53:54 PDT 2007


Darryl B wrote:
> Tango has this great log library in the tradition on log4j (Or Phyton, if you
> prefer). It provides loggers configured in a hierarchy, gives output functions
> for differing levels, automatically finds infinite loops in code, makes
> coffee, and general tells you that you are a great person and that you're just
> a stellar example of your race.
> 
> Well, it does some of those things anyway. In the end, it's a pretty decent
> log module, other than, it assumes what you're logging is a 'string' of some
> sort, but that's a topic for another time. You want to log, and it's strings
> you want in there, it pretty much covers all the bases.
> 
> With that love fest out of the way, it's a great big cup of cold yummy milk
> (and you like milk, for the purposes of reading this post, even if you really
> don't), but there's a fly in it. (Also for post reading, you don't like flies).
> 
> Yeah, you can work around the fly, take it out with a spoon, whatever, but
> it's sort of ruined the otherwise great milk you had there, and you can still
> drink it, but you sort of don't want to, though there's really nothing wrong
> with it.
> 
> So, here's the fly in my cup of milk: I really want to log formatted output. I
> can log normal strings without restraint, calling
> 
> 'log.info("grab milk from the store tonight");'
> or
> 'log.warn("mother in law is coming");'
> 
> and that's all great.
> 
> But I want to put some variable data in there (as I suspect is what is mostly
> done while logging). What I _want_, is to do something like:
> 
> 'log.info.format("grab {} from the {} {}", "beer", "pub", "right now");'
> or
> 'log.warn.format("{} is {}", "Phobos Developer", "coming this way.");'
> 
> However, this can't work _and_ take advantage of anonymous delegates (ala
> 'lazy'), because the 'log.warn' is going to have to evaluate the format (to
> call it).
> 
> The current workaround is to call it via:
> 
> 'log.info(log.format("{} is really {}", "this", "ugly"))'
> 
> Which is absolutely optimal from a 'omg your code runs like a racehorse' point
> of view. Unfortunately, it fails the 'your code looks like someone got
> horribly sick somewhere, could only find a bag to put it in, and so decided to
> stash it right there where you format your info log output' test.
> 
> I've been studying over the forum archives back from about a year ago, spoke
> with some people on IRC, and played with every strange and off-the-wall
> thoughts I had , and I can't see a solution (without macros) to call this
> oft-used function with less risk of carpal tunnel and the slight increase in
> blood pressure everytime I type it out completely.
> 
> So, here I am, telling my tale of sadness, hoping someone might have an
> insight that I have not. Otherwise, I guess I'll be forced to take this
> arg.info(arg.format()) girl to the prom, but I sure hope none of my friends
> see me.

It can be done; just replace the current functions with structs equipped 
with opCall and format.

private struct LogCaller {
         Level level;
         Logger opCall (string msg) {
                 return append (level, msg);
         }

         void format (char[] buffer, char[] formatStr, ...) {
                 level.format (buffer, formatStr, _arguments, _argptr);
         }

         static LogCaller opCall (Level level) {
                 LogCaller caller;
                 caller.level = level;
                 return caller;
         }
}

The remainder of the work is a bit less than obvious. Maybe a template 
taking an alias parameter -- the code uses static fields on Logger to 
determine what to append to.



More information about the Digitalmars-d mailing list