- Article pages now have a discussion option at the bottom (moderated/captcha, but no registration needed)

Collapsing Functions

What is a "Collapsing Function"?

A collapsing function is a function whose behavior changes depending upon the circumstances under which it's run. Function collapsing is useful when you find yourself repeatedly checking a variable whose value never changes.

How do I make a function collapse?

Function collapsing requires some static feature in the environment. A common example is a script that gives the user the option of having "verbose" output.

#!/bin/bash

[[ $1 = -v || $1 = --verbose ]] && verbose=1

chatter() {
  if [[ $verbose ]]; then
    chatter() {
      echo "$@"
    }
    chatter "$@"
  else
    chatter() {
      :
    }
  fi
}

echo "Waiting for 10 seconds."
for i in {1..10}; do
  chatter "$i"
  sleep 1
done

How does it work?

The first time you run chatter(), the function redefines itself based on the value of verbose. Thereafter chatter doesn't check $verbose anymore, it simply is. Further calls to the function reflect its collapsed nature. If verbose is unset, chatter will echo nothing, with no extra effort from the developer.

More examples

FIXME Add more examples!

# Somewhat more portable find -executable
# FIXME/UNTESTED (I don't have access to all of the different versions of find.)
# Usage: find PATH ARGS -- use find like normal, except use -executable instead of
# various versions of -perm /+ blah blah and hacks
find() {
  hash find || { echo 'find not found!'; exit 1; }
  # We can be pretty sure "$0" should be executable.
  if [[ $(command find "$0" -executable 2> /dev/null) ]]; then
    unset -f find # We can just use the command find
  elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then
    find() {
      command find "${@//-executable/-perm \/u+x}"
    }
  elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then
    find() {
      command find "${@//-executable/-perm +u+x}"
    }
  else # Last resort
    find() {
      command find "${@//-executable/-exec test -x '{}' \; -print}"
    }
  fi
  find "$@"
}

#!/bin/bash
# Using collapsing functions to turn debug messages on/off

[ "--debug" = "$1" ] && dbg=echo || dbg=:


# From now on if you use $dbg instead of echo you can select if messages will be shown

$dbg "This message will only be displayed if --debug is specified at the command line

Discussion

Enter your comment. Wiki syntax is allowed:
 
howto/collapsing_functions.txt · Last modified: 2010/04/21 06:36 (external edit)
GNU Free Documentation License 1.3
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0