Express What, not How.

Brian McNamara! gt5163b at prism.gatech.edu
Thu Oct 16 22:48:14 EDT 2003


Raffael Cavallaro <raffaelcavallaro at junk.mail.me.not.mac.com> once said:
>In other words, the higher the level of abstraction, the more we are 
>talking in the language of the problem domain. The language of the 
>problem domain has a vocabulary with _names_ for entities and their 
>interactions. Anonymous functions, by definition _have_no_names_, so 
>they can't possibly be isomorphic with the language of the problem 
>domain. If an anonymous function _does_ accomplish something identical 
>to a named entity or interaction in the problem domain, then you should 
>give your anonymous function _that_name_ from the problem domain. Now, 
>of course, it is a named function or macro, not an anonymous function 
>anymore.

I still disagree.  Below is an example where I still think it's best to
use anonymous functions, despite the fact that both (1) it's at a high
level of abstraction and (2) it maps exactly to the problem domain.

Here's the example.  You've got some command-line application that
processes some binary files.  The details aren't important.  You can
run the program like this:

   % prog foo bar baz
      # processes data files foo, bar, and baz, and then
      # saves binary results in foo.sav, bar.sav, and baz.sav

or like this

   % prog -p foo
      # processes data files (in this case, just "foo")
      # and prints human-readable results to the screen

Hopefully you get the basic idea for the application.


Now, I can imagine the program being structured something like this.
(I'm using Haskell, which is the FPL I know best, but it's not my native
tongue, so apologies if I screw up minor details.)

   processFile :: String -> IO Info
   -- process data file named by string, return Info data structure
   
   printInfo :: Info -> IO ()
   -- print Info in human-readable form to stdout
   
   saveInfo :: Info -> String -> IO ()
   -- save Info (in binary) to file named by String

Now, somewhere in or near the main() function (that is, at the very
highest level of abstraction for this program), I can imagine seeing
code like this:
   
   -- assume these vars:
   fileList  :: [String]  -- names of files to process
   wantPrint :: Bool      -- whether user specified '-p' option
   ...
   let forEachFilename op = mapM op fileList
   in if wantPrint
      then forEachFilename \fn -> do info <- processFile fn
                                     printInfo info
      else forEachFilename \fn -> do info <- processFile fn
                                     saveInfo info (fn++".sav")

Note the two anonymous functions:

   \fn -> do info <- processFile fn
             printInfo info
and
   \fn -> do info <- processFile fn
             saveInfo info (fn++".sav")

Note that they map exactly to ideas from the problem domain (actually,
to the very user interface of this program).  Now, you want me to make
these separate named functions?  What ought I call them?  Perhaps
"processFileAndPrint" and "processFileAndSave"?  Or perhaps we should
use the name as it's known in the user interface, and name them
"doItWithTheDashPeeOption" and "doItWithoutTheDashPeeOption"?

I think that such a strategy would be silly, especially if there is
more than one command-line option, each of which slightly alters the
program's overall behavior.  I think that the anonymous functions do a
good job of succinctly specifying the behavior for each option.


I have enjoyed this discussion because it's forced me to think about
what rules I apply when making coding choices (such as whether-or-not to
use an anonymous function).  I've found it's surprisingly difficult to
come up with succinct, precise, hard-and-fast rules which capture how I
choose to write code.  You have an advantage here: even if we disagree
about what the "best" style is, you can at least describe the rules for
your style, whereas I cannot easily do the same for mine.

-- 
 Brian M. McNamara   lorgon at acm.org  :  I am a parsing fool!
   ** Reduce - Reuse - Recycle **    :  (Where's my medication? ;) )




More information about the Python-list mailing list