Monthly Archives: February 2014

The less-familiar parts of Lisp for beginners — function-keywords

Next on the tour of uncommon Lisp features is function-keywords.  I can’t really think of a time when a programmer might need to use this, it is a function that one typically would use in the implementation of the generic function framework in Common Lisp, as part of the system to determine whether a particular method matches a particular generic function definition.

If any reader can find a context, outside of implementing Lisp, when the programmer might need to use this, please let me know in the comments.

The less-familiar parts of Lisp for beginners — function

Continuing our alphabetical tour through Lisp features that the newcomer might not have previously encountered, we arrive at function.

There are two common use cases for this special operator.  One is to interpret a function name in the current lexical environment and return the appropriate function object.  The other is to build lexical closures.

The first case was discussed some in the article on fboundp.  Recall that a function name defined by labels is not visible to called functions.  So, passing the name of a function defined with labels into, say, the predicate of the sort function will fail because sort will try to look up the function name in the set of interned symbols, and labels does not influence the set of interned symbols.  The function special operator allows the programmer to resolve the name in the lexical environment and use it to pass not the name of the function, but the actual function object itself.  Here is an example, first with incorrect syntax that raises an error:
 

(defun demonstrate-function ()
  (let ((input-list (list 10 2 4 9 5)))
    (labels
        ((even-odd-sort (v1 v2)
           "Sorts the values, but even numbers are always less than odd."
           (cond
             ((evenp v1)
              (or (oddp v2)
                  (< v1 v2)))
             (t
              (and (oddp v2)
                   (< v1 v2))))))

      (format t "Before sorting: ~A~%" input-list)
      (format t "After sorting: ~A~%" (sort input-list
                                            'even-odd-sort)))))

Running produces this:
 
CL-USER> (demonstrate-function)
Before sorting: (10 2 4 9 5)
; Evaluation aborted on #<UNDEFINED-FUNCTION EVEN-ODD-SORT {100544DAC3}>.

The reason this failed is that labels did not insert even-odd-sort into the set of interned symbols.  When the sort function received the symbol ‘even-odd-sort, it had no way to look up the function attached to that symbol.  In fact, if labels had been used to shadow an existing defun called even-odd-sort, then sort would have used the defun one, as that symbol would be interned.

The solution is to pass to sort the actual function code itself, rather than passing a  name and asking sort to look it up.  This is done with the function special operator:
 

(defun demonstrate-function ()
  (let ((input-list (list 10 2 4 9 5)))
    (labels
        ((even-odd-sort (v1 v2)
           "Sorts the values, but even numbers are always less than odd."
           (cond
             ((evenp v1)
              (or (oddp v2)
                  (< v1 v2)))
             (t
              (and (oddp v2)
                   (< v1 v2))))))

      (format t "Before sorting: ~A~%" input-list)
      (format t "After sorting: ~A~%" (sort input-list
                                            (function even-odd-sort))))))

Producing this output:
 
CL-USER> (demonstrate-function)
Before sorting: (10 2 4 9 5)
After sorting: (2 4 10 5 9)
NIL

Because the passing of function objects is a fairly common operation, there is a Lisp reader shorthand for this.  The code (function name) can be abbreviated #’name.

The second case, building a function closure, is demonstrated in the CLHS entry for function.  Here is it in use:
 

CL-USER> (defun adder (x)
           (function (lambda (y) (+ x y))))
ADDER
CL-USER> (let ((my-adder-10 (adder 10)))
           (format t "Calling my-adder-10 on the number 3: ~D"
                   (funcall my-adder-10 3)))
Calling my-adder-10 on the number 3: 13
NIL

This is, perhaps, a good place to talk a bit about closures.  The function adder returns a closure.  While the beginner might have run into that term, there is sometimes a tendency to think of a closure as a “function object”, but that entirely misses the meaning.  A closure is actually the lexical environment, the variables, that are available for the function(s) within it.  In this case, the closure retains the variable ‘x’.  Not the value of that variable, but the variable itself.  Functions contained within the closure can modify the variable, and those modifications are retained.  That is, the adder function above did not return a function that adds 10, it returned a function that adds ‘x’, and the closure holds the value of ‘x’, which happens to be 10 here.

One more bit about closures.  I once wrote some code which contained an error.  It was for starting a number of threads, and giving each of them its own index.  This was for doing some parallel matrix calculations, so different threads had to know which part of the matrix they were responsible for solving.  The code to start it up seemed simple enough, and I excerpt some of it here:
 

(defun spawn-thread (fcn &rest args)
  #+(and sbcl sb-thread) (sb-thread:make-thread #'(lambda ()
                                                    (apply fcn args)))
  #+(and sbcl (not sb-thread)) (error "Cannot call 'spawn-thread' because the environment does not support threads.")
  #-(or sbcl) (error "We need an implementation of thread starting for this platform"))

(defun start-workers ()
  (dotimes (j *number-of-worker-threads*)
    (push (threads:spawn-thread 'threaded-solver 
                                frame j 
                                *number-of-worker-threads*) 
          *thread-list*)))

This didn’t work.  Sometimes several threads all worked on the same block of the matrix, leaving parts of it unsolved.  They weren’t getting unique values of ‘j’.  The reason for this is that spawning the worker operates in two steps.  First, a new thread is spawned, and then the arguments are passed to the ‘threaded-solver function.  There is a race condition here, once the thread was spawned, it was waiting around to pass the value of ‘j’ to the worker function, but meanwhile the parent thread was still running, and it was eager to increment ‘j’.  The solution to this is to capture ‘j’ in a closure:
 

(defun start-workers ()
  (dotimes (j *number-of-worker-threads*)
    (let ((closure-j j))
      (push (threads:spawn-thread 'threaded-solver 
                                  frame closure-j
                                  *number-of-worker-threads*) 
            *thread-list*))))

With this change, the race condition disappeared.

The less-familiar parts of Lisp for beginners — ftype

Continuing the discussion of Lisp features not necessarily encountered by a brief introduction to the language, we come to ftype.  This is a declaration, used within a declare, declaim, or proclaim, to provide a hint to the compiler as to what the inputs and outputs are of a particular function.  Because Lisp is not strongly typed, it often has to do run-time type checking on operations, and by declaring the types to the compiler, the programmer allows the compiler to avoid those run-time checks, and so can produce better optimized code.

The CLHS provides these examples:
 

(declare (ftype (function (integer list) t) ith)
         (ftype (function (number) float) sine cosine))

The first line declares that the function ith takes two arguments, the first being an integer, the second being a list.  Its output is declared to be t, which matches any legal Lisp type (i.e. nothing is said about the output type).

The second line declares that the sine and cosine functions each take a numeric argument and return a float.  Note that sine and cosine are not the names of those trigonometric functions in the Lisp standard, these will be user-defined functions of non-complex arguments.  The types of the standard sin and cos functions are a bit more complicated, as they account for single and double precision real or complex return values.

The less-familiar parts of Lisp for beginners — fmakunbound

Next in the list of Lisp features I’m reviewing here is fmakunbound.  There isn’t very much to say about this if you understand the behaviour of packages and intern, covered in this earlier article.  The fmakunbound function causes the function field associated with the symbol to be discarded.  If that symbol formerly had a function field associated with it, allowing the function to be invoked by interpreting the symbol in a function context, then that method of invocation is no longer available.

As with fboundp, fmakunbound does not see lexically scoped symbols, it only acts on the set of interned symbols, so it does not affect behaviour driven by flet, labels, or macrolet.

The less-familiar parts of Lisp for beginners — flet

Now, we’re going to switch a little bit, because I’m discussing flet.  Unlike many of the commands I’ve been talking about, the beginner Lisp programmer is quite likely to have encountered flet in introductory material.  Depending on the source, though, the distinction between flet and labels may not have been made particularly clear, so that’s what I’ll be talking about here.

The flet special operator, like labels, modifies the lexical environment, and like labels it does not intern a new symbol.  The difference is that the forms in the flet do not, themselves, see those modifications to the lexical environment.  For purposes of writing the forms within flet, symbols are resolved according to the enclosing environment.  This means, for instance, that flet-defined functions cannot call themselves recursively.  This is the difference between flet and labels.  Examples may help.

In the code below, I write a pair of global functions, func-A and func-B.  If func-A is called, it recursively calls func-A, then calls func-B.  Output appears on the screen to show what functions are being called.  I then shadow these functions with forms in flet, in demonstrate-flet, and labels, in demonstrate-labels.  The new definitions are exactly the same as the global ones, save for the text that is printed, to demonstrate which version of the function is being called.  As you can see, under the flet, the invocation of func-A calls the one defined in the flet, but within the flet, the recursive call to func-A calls, instead, the global symbol function.  On the other hand, under labels, the recursive call to func-A calls itself, the definition in the labels statement.
 

(defun func-A (&optional (depth 0))
  (format t "~V,0TThis is depth ~D of global symbol table func-A~%"
          (* depth 10) depth)
  (when (= 0 depth)
    (format t "Calling the functions func-A and func-B...~%")
    (func-A (1+ depth))
    (func-B (1+ depth))))

(defun func-B (&optional (depth 0))
  (format t "~V,0TThis is depth ~D of global symbol table func-B~%"
          (* depth 10) depth))

(defun demonstrate-flet ()
  (flet 
      ((func-A (&optional (depth 0))
         (format t "~V,0TThis is depth ~D of flet func-A~%"
                 (* depth 10) depth)
         (when (= 0 depth)
           (format t "Calling the functions func-A and func-B...~%")
           (func-A (1+ depth))
           (func-B (1+ depth))))

       (func-B (&optional (depth 0))
         (format t "~V,0TThis is depth ~D of flet func-B~%"
                 (* depth 10) depth)))

    (func-A)))

(defun demonstrate-labels ()
  (labels 
      ((func-A (&optional (depth 0))
         (format t "~V,0TThis is depth ~D of labels func-A~%"
                 (* depth 10) depth)
         (when (= 0 depth)
           (format t "Calling the functions func-A and func-B...~%")
           (func-A (1+ depth))
           (func-B (1+ depth))))

       (func-B (&optional (depth 0))
         (format t "~V,0TThis is depth ~D of labels func-B~%"
                 (* depth 10) depth)))

    (func-A)))

Output:
 
CL-USER> (demonstrate-flet)
This is depth 0 of flet func-A
Calling the functions func-A and func-B...
          This is depth 1 of global symbol table func-A
          This is depth 1 of global symbol table func-B
NIL
CL-USER> (demonstrate-labels)
This is depth 0 of labels func-A
Calling the functions func-A and func-B...
          This is depth 1 of labels func-A
          This is depth 1 of labels func-B
NIL