Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

Edit: Ohhh! I see! The message isn't evaluated until after! Got it.

I don't understand why this is special?

Why can't you rewrite log.debug to include the check?

    func debug(m string) {
        if log.isDebugEnabled() {
            log.debug(m);
        }
    }
What makes macros special in this case?


The point was that "debug" and "message" parts in the example were arbitrarily complex expressions which were computationally expensive to evaluate. Your wrapping of log debug would still require evaluating them to get the message string unconditionally, even when debug logging is not enabled.

Of course, with support for first-class functions, you could do something like:

  func debug(produceMessage ()->string) {
    if log.isDebugEnabled() {
      log.debug(produceMessage());
    }
  }


And then what would I need to type to write a log message?


You pass a lambda that returns the debug message. With javascripty syntax:

    debug( function(){ return "my expensive log message" })
BTW, if your language is lazily evaluated (like Haskell) then you don't need to do this because arguments will only ve evaluated when they are needed.


The downside there is you can still end up allocating a closure. Whereas an expanded macro shouldn't cost anything. (A sufficiently smart compiler might be able to optimize the closure allocation.)


A sufficiently modern language (like, saaaaay, D2) could also give you a type like "closure you don't intend to escape" (let's call this a "scoped closure", or if you will, "scope string delegate()"), and eschew allocation entirely without requiring optimization.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: