The less-familiar parts of Lisp for beginners — fboundp

Next, we have fboundp.  This is another function for querying the state of the Lisp environment, asking whether a particular name is bound to a function or macro.  This function does not determine whether the name is interned as variable name.  Recall that, unlike C++, the Lisp language syntax unambiguously distinguishes between variable names and function names.  Consequently, these two types of symbols are not at risk of namespace collisions.

Now, you might think that this makes fboundp very simple.  The temptation is to say that if fboundp on a symbol returns nil, then calling that symbol in a function context will always fail, but things are a bit more complicated than that.  The fact is that it is possible to create named functions and macros which are not inserted into the global/persistent Lisp function namespace, but instead have a limited scope, following which time the functions effectively disappear.  The features labels, flet, and macrolet do this.  If, in your reading, you’ve seen a reference to “lexical functions”, the labels and flet features are what create them, and fboundp does not see lexical functions or macros.

And from this starting point, we can gain some helpful insight into the way Lisp works…

When one of labels, flet, or macrolet is used, it does not insert a new entry into the function symbol table, but it does shadow any existing functions with that name in the same scope.  If labels did insert an entry into the function symbol table, that would interfere with the view seen by other threads of execution.

This distinction between names in the function symbol table and names constructed by labels, flet, or macrolet manifests itself in one of the less obvious syntax requirements.  There are many contexts where the programmer can pass a function by referring to its symbol.  If the programmer has decided to use labels to build a function that happens to collide with an existing name in the function symbol table, how can he tell the program which one to use?  When passing a name that is not in the function symbol table, then rather than using a single-quote to quote the name, one must use a number sign followed by the single quote.  This is demonstrated here:

CL-USER> (defun my-adder (x)
           (+ x 2))
CL-USER> (labels
             ((my-adder (x) (+ x 3)))
           (mapcar 'my-adder '(1 2 3)))
(3 4 5)
CL-USER> (labels
             ((my-adder (x) (+ x 3)))
           (mapcar #'my-adder '(1 2 3)))
(4 5 6)

I begin by creating a function called my-adder in the function symbol table, one that adds 2 to the numbers passed to it.  Then, I use labels to shadow my-adder with a new definition, one that adds 3 to the numbers passed.  Note, though, that when I use the symbol ‘my-adder in mapcar, the one that is used is the one in the defun, not the one that I supposedly used to shadow it.  In order to use my new definition of my-adder, I have to use the #’my-adder syntax.  It is important to understand the difference between these two cases, and why the different forms are necessary.

It helps to understand what these notations are doing.  What, exactly, is the difference between mapcar acting on ‘my-adder and acting on #’my-adder?  In the first case, the mapcar function is called with a symbol as a parameter.  Inside mapcar, the symbol is resolved in the function symbol table to obtain the function that is to be used for the operation.  That is, mapcar is told “use the function whose symbol is designated by ‘my-adder“.  The second case, #’my-adder, is entirely different.  The # prefix is a reader macro that converts the text at load time.  The sequence #’my-adder is replaced by the text sequence (function my-adder) before the Lisp instance even sees it.  The function special operator resolves the name in the current lexical environment (before the mapcar function call), and returns a function object, not a symbol.  The mapcar function, rather than receiving a symbol and being told to look it up, receives a bare function itself, and uses that, without further resolution.

Perhaps now, there is a realization dawning.  You know that familiar construct for passing anonymous functions, lambdaWe start with a quoted list, the car of which is the keyword lambda.  Then, by prefixing the #, we convert this list into a function in the current lexical environment, and that function is what is passed downwards.  In effect, when we pass a function as a parameter, we can either choose to pass it by name, by sending a symbol down, or by value, by resolving the symbol into an actual function object and passing that instead.  And that is the difference between these two syntaxes, and the # prefix is a read-time shorthand for the second case.  Edit #3: 2014-02-27.  This phrasing was awkward, and now that we’ve covered read-macros under gensym, and have a separate article for lambda, this struck-out text should be ignored.  Instead, please refer to the article about lambda for more details.  The final point is this: many Lisp features which accept functions as arguments can be passed either a symbol from which the function is to be retrieved, or simply the bare function itself.  For functions that are not bound to a symbol, like those created with labels, flet, or lambda, it it necessary that the function object itself be passed.  The function object is retrieved within the scope where it is visible with the function special operator, for which #’ is a read-macro shortcut.  Finally, Common Lisp defines a lambda macro that expands to include the invocation of function, so the #’ is technically optional on lambda forms.

Edit #1:  2014-02-01

Some criticism has been raised on other sites about the terms and descriptions above.  It has been noted that referring to something like the “function symbol table” may confuse more than illuminate, as that is not a term commonly used.  I apologize for this, and it’s a good point to bring up.  My tendency in this series has been to try to describe logical parallels directed at the C++ programmer.  Not an excuse, merely an explanation.  But I certainly appreciate that the language I use above is strange or off-putting to a veteran Lisp programmer, a category in which I emphatically do not include myself.

I sincerely hope that when I reach the intern function, that the description I provide then will be more familiar and provide a better view of what is really going on.

For now, if you’ve read the original text above, and seen me talking about a “function symbol table”, don’t attach too much to that.  The underlying concept, I hope, is helpful.  There exists an mechanism in the Lisp image that allows a function to be referenced by its symbol.  The labels form, while superficially similar to defun, is, in fact, notably different in that it does not influence this aforementioned mechanism, and so does not interfere with the resolution of that symbol in other forms.

I also invite others to post copies of their comments and criticisms here, if they so desire.  I don’t want confusing or misleading postings to sit uncorrected on this site, while helpful criticism sits on other web sites that the casual visitor might not have come across.  I’ll point out that my motivation for writing this series of postings is to improve my understanding of Lisp, and deliberately researching every feature that I haven’t had the opportunity to use.  These posts are primarily an educational tool for myself, but I hope they help others.  If I say something wrong or confusing, please let me know.

Edit #2:  2014-02-02

I’ve posted an out of sequence article about interned symbols and packages here.  I hope that this provides more clarity, and invite the reader to go over that material carefully in order to avoid being mislead by some of the less precise terms I’ve been using in this series of posts.  Once again, I invite comments if the more experienced readers feel I’m failing to give helpful explanations.

2 thoughts on “The less-familiar parts of Lisp for beginners — fboundp

  1. For those who are interested in how the Common Lisp code translates to Emacs Lisp, the elisp code counterpart is the same except for replacing labels with cl-labels, and the output is the same as Common Lisp. What may be a gotcha for elisp beginners is that this producing the same result as the Common Lisp counterpart is a feature of cl-lib, not of Elisp. cl-labels takes care to differentiate between (function my-adder) and (quote my-adder), but outside of cl-lib macros, both (function my-adder) and (quote my-adder) evaluate to a symbol in elisp.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


反垃圾邮件 / Anti-spam question * Time limit is exhausted. Please reload CAPTCHA.