I uses traces quite a bit to make sure that code is doing what I expect (or figure out why it is not). Alhough I'm compulsive about making my traces readable, I like to keep my code base as uncluttered as possible. Here's a hack I came up with that helps me to meet these constraints.

Problem Statement

The SketchApps plugin framework includes logging methods that will output one or more lines of text, eg:

@pf.log.debug   'foo      ' + i(foo) if true #T

@pf.log.debug [ 'foo      ' + i(foo),
                '  ' + i( ] if true #T

This produces nice output, but it's a hassle to create and maintain. Also, if there are several values, the tracing code can become voluminous. So, I wanted a shorthand way to create traces.


A method can accept arbitrary parameter values (eg, variables, method calls), but getting labels for the values is tricky and brittle. However, some pre-processing and the use of eval in the calling code lets me step around the problem, eg:

l = %w[ foo ]
@pf.log.debug( @pf.x(l).map {|i| eval(i) } ) if true #T

The above example works as follows:

  • Create a list of strings containing variables, method calls, etc.

  • Massage the strings into a form suitable for use by eval.

  • eval each string in the list, via map.

  • Run @pf.log.debug on the resulting list.

Possible Concerns

Some readers may have concerns about the use of eval, fearing that it might lead to inefficient and/or insecure code. My take is that:

  • Inefficiency is not a problem in the context of traces.

  • Given that eval's input is defined by the program,
    use of eval should not add any security problems.

Supporting Code

class PF_Main
  def x(names)
  # Expand an Array of (method or variable) names
  # into an Array of Strings suitable for use by eval.
  # A solitary underscore (_) produces a spacer line.
  # Typical usage:
  #   names   = %w[ @comp_key @item_key _ ]
  #   @pf.log.debug( @pf.x(names).map {|l| eval(l) } )

    format    = "'%-20s  ' + i(%s)"
    eval_strs = do |n|
      n == '_' ? "''" : ( format % [ "#{ n }", n ] )

This wiki page is maintained by Rich Morin, an independent consultant specializing in software design, development, and documentation. Please feel free to email comments, inquiries, suggestions, etc!

Topic revision: r4 - 02 Jan 2012, RichMorin
This site is powered by Foswiki Copyright © by the contributing authors. All material on this wiki is the property of the contributing authors.
Foswiki version v2.1.6, Release Foswiki-2.1.6, Plugin API version 2.4
Ideas, requests, problems regarding CFCL Wiki? Send us email