"constant is being redefined" with defconstant? - common-lisp

I'm reading chapter 5.2 of PAIP. And when I try define a constant using the following form, taken exactly from the book, I get the error shown below. I'm using SBCL 1.1.14.debian as the interpreter. What am I doing wrong?
(defconstant no-bindings '((t . t))
"Indicates pat-match success, with no variables.")
The constant NO-BINDINGS is being redefined (from (T T) to ((T . T)))

The error means that you have done a previous definition of the same name no-bindings with the value '(T T).
For instance in the REPL you have done a definition:
(defconstant no-bindings '(t t)
"Indicates pat-match success, with no variables.")
and then you have redefined no-bindings with:
(defconstant no-bindings '((t . t))
"Indicates pat-match success, with no variables.")
The manual specifies:
A constant defined by defconstant can be redefined with defconstant. However, the consequences are undefined if an attempt is made to assign a value to the symbol using another operator, or to assign it to a different value using a subsequent defconstant.
Updated
Note that in SBCL, even a double definition of the same value, for instance, writing twice in the REPL:
(defconstant no-bindings '((t . t))
"Indicates pat-match success, with no variables.")
causes a constant redefinition error, while in other systems (I tried CCL), this does not happen. Actually this is due to the interpretation of "different value" in the above definition. The Glossary says the different is not the same, and same is not eql, and
(eql '((t . t)) '((t . t)))
gives NIL, while other equality operators, as, for instance:
(equal '((t . t)) '((t . t)))
returns T.
So, it seems that SBCL follows correctly the formal specification, differently from other systems.

A constant is per spec a value that is not suppose to be changed.. Thus you should use it for absolute certainties like (defconstant +pi+ 3.1415927).
In practice it's changeable, but every function or macro where it has been used might have taken advantage of it being a constant and compiled in the actual value so changing it won't be affected by those. Thus changing a constant should be done by a complete recompile/reload of everything to make make sure it's updated.
For values that are considered constant but you might change, use defparameter. eg. (defparameter *no-bindings* '((t . t)) "Indicates pat-match success, with no variables.").

Related

Unreachable code within Cond recursive function -- why?

With my recursive function, I have a cond with a fail conditon.
When the concequence of the fail condition is nil, everything works fine.
But when I try to change the concequence of the fail condition to something else:
(defun rec ()
(cond ((null t) (format t ....))
....)
it says that the (format t....) function is unreachable... why?
In Common Lisp, t is a boolean constant that means “true”. So, the expression (null t) checks if t is the empty list and this is obviously always false. So the compiler is smart enough to infer that the code (format ... is never reached and does not compile it.
Errors like this arise sometimes when one forgets the meaning of t, and tries to use it as a variable.

SBCL-specific declaim

SBCL generates spurious style warnings about undefined functions. (The functions are defined, just later in the file.) I want to solve this problem once and for all. Fortunately, there is a way to do this:
(declaim (sb-ext:muffle-conditions style-warning))
The downside is that CCL, for obvious reasons, barfs on a program containing the above. I try to solve this problem with a conditional:
(#+sbcl (declaim (sb-ext:muffle-conditions style-warning)))
but now SBCL is unhappy: "illegal function call".
How do you put such a declaim into a portable program?
Note that while the existing answer is right, disabling warnings is not a good practice. In your case, it is probably not necessary.
Common Lisp has a notion of compilation unit, where multiple definitions are grouped together. This gives a chance for the compiler/interpreter to take care of cross-references among functions (an interpreter could collect warnings and keep only those that are not found later, for example).
For example, in file #P"/tmp/foo.pl":
(defun mut-rec-foo (x)
(when (plusp x)
(mut-rec-bar (1- x))))
(defun mut-rec-bar (x)
(print x)
(mut-rec-foo (1- x)))
Do not evaluate anything in the file; instead do:
(compile-file #P"/tmp/foo.pl")
; compiling (DEFUN MUT-REC-FOO ...)
; compiling (DEFUN MUT-REC-BAR ...)
; /tmp/foo.fasl written
; compilation finished in 0:00:00.002
No warning. You can then call (load #P"/tmp/foo.fasl") to have the definitions in your current lisp environment, without warnings.
Typically, ASDF and by extension Quicklisp use COMPILE-FILE, so your problem should disappear as soon as you bundle your files into a system.
You can also do:
(with-compilation-unit ()
(defun mut-rec-foo/bis (x)
(when (plusp x)
(mut-rec-bar/bis (1- x))))
(defun mut-rec-bar/bis (x)
(print x)
(mut-rec-foo/bis (1- x))))
Evaluating the whole block shows no warning for *EVALUATOR-MODE* being both :COMPILE or :INTERPRET.
What you witnessed happens when you evaluate each expression one after the other (or maybe one region after another one). There, the compiler has no way to know that the function already exists. Silencing the warning is the worse option, because you might actually have made an error.
If you know in advance that a function will exist, but not in your compilation unit (maybe it is only defined at runtime), the you can declaim that fact, as follows:
(declaim (ftype function my-function))
The above says that my-function must be assumed to be fbound to an object of type function. You could also give more information by refining what kind of function you claim it to be:
(declaim (ftype (function (number) (values string &optional)) num-to-string))
... for a function that accepts a number and returns exactly one value, a string.
(declaim (ftype (function () nil) forever-loop))
... for a function that accepts nothing and never return a value (loop or signals an error).
Omit the outer pair of parentheses:
#+sbcl (declaim (sb-ext:muffle-conditions style-warning))
As you are using declaim, I assume, that the declaration appears at the top-level of a compilation unit. If you need to group multiple top-level statements, you can wrap them all with a progn (which doesn't change the "top-level"-ness).
The reason SBCL did complain is, that its reader reads
((declaim (sb-ext:muffle-conditions style-warning)))
(as the :SBCL feature is present), which is simply a syntax error. CCL does not complain, because its reader reads
()
which is simply another way to spell nil.

Recursive Loop in Clojure via Macro is throwing me errors

I've been trying to write a recursive loop in clojure that will print me out the very last number in the list. The point is not that I need to get the last number (for which I'm sure there's a built in function for that) but that I want to better understand recursion and macros in clojure. So I have this macro...
(defmacro loop-do [the-list]
`(if (= (count '~the-list) 1)
(println (first '~the-list))
(loop-do (rest '~the-list))))
But I get a stackoverflow error. What am I doing wrong?
How will people use your macro?
Somewhere, someone will call:
(loop-do list)
As a piece of code, those are only two symbols in a list. The first one is recognized as your macro, and the second one, list, is a symbol that represents a variable that will be bound at runtime. But your macro only knows that this is a symbol.
The same goes for:
(loop-do (compute-something))
The argument is a form, but you do not want to get the last element of that form, only the last element of the list obtained after evaluating the code.
So: you only know that in your macro, the-list will be bound to an expression that, at runtime, will have to be a list. You cannot use the-list as-if it was a list itself: neither (count 'list) nor (count '(compute-something)) does what you want.
You could expand into (count list) or (count (compute-something)), though, but the result would only be computed at runtime. The job of the macro is only to produce code.
Recursive macros
Macros are not recursive: they expand into recursive calls.
(and a b c)
might expand as:
(let [a0 a] (if a0 a0 (and b c)))
The macroexpansion process is a fixpoint that should terminate, but the macro does not call itself (what would that mean, would you expand the code while defining the macro?). A macro that is "recursive" as-in "expands into recursive invocations" should have a base case where it does not expand into itself (independently of what will, or will not, happen at runtime).
(loop-do x)
... will be replaced by:
(loop-do (rest 'x))
... and that will be expanded again.
That's why the comments say the size actually grows, and that's why you have a stackoverflow error: macroexpansion never finds a fixpoint.
Debugging macros
You have a stackoverflow error. How do you debug that?
Use macroexpand-1, which only performs one pass of macroexpansion:
(macroexpand-1 '(loop-do x))
=> (if (clojure.core/= (clojure.core/count (quote x)) 1)
(clojure.core/println (clojure.core/first (quote x)))
(user/loop-do (clojure.core/rest (quote x))))
You can see that the generated code still contains a call to usr/loop-do , but that the argument is (clojure.core/rest (quote x)). That's the symptom you should be looking for.

Unbound variable in Allegro

In example code in a book I'm reading, there's a line for a macro that provides shorthand for getting the global value of a symbol:
(defmacro sv (v) '(symbol-value `,v))
However, Allegro sees V as an unbound variable. I don't know how to change this macro to return the correct result, because I've never encountered a problem like this before. How would I get the global value of any symbol? Thanks for your help!
You need a backquote, not a single quote, in front of the whole s-exp:
(defmacro sv (v) `(symbol-value ,v))
(I know, it's hard to see: Just move the backquote in your original s-exp from in front of ,v and replace the single quote at the beginning of '(symbol-value ...)).
Backquote operates on expressions (lists), not individual atoms, per se. If what you typed was actually in the book, it's likely an erratum.
A slightly better version of sv:
(defmacro sv (v) `(symbol-value (quote ,v)))
or
(defmacro sv (v) `(symbol-value ',v))
In the last version, interchange the backquote and single quote in your original code. The penultimate version just makes it easier to read.
However, symbol-value only queries the current value bound to the variable. For example, this code evaluates to 'something-else:
(defparameter *wombat* 123)
(let ((*wombat* 'something-else)) (sv *wombat*))
The *wombat* in the let form is a lexical variable, whereas the *wombat* in the defparameter form is dynamic. The let form temporarily hides the visibility of the defparameter.

Why does common lisp's case construct always match True (T)?

This is with SBCL 1.0.55 on Debian squeeze. I'm probably missing something obvious, but I'm a beginner, so please bear with me.
CL-USER> (defparameter x 0)
CL-USER> (case x (t 111) )
111
So it looks like case here is matching the variable x with the truth symbol t. This happens with everthing I've tried; this x is just an example. I don't see why this would happen. Since case uses eql for matching, I tried
CL-USER> (eql x t)
NIL
So, eql does not match x and t. What am I missing? Thanks in advance.
Described in the CASE documentation.
otherwise-clause::= ({otherwise | t} form*)
The syntax says that an otherwise clause is either (otherwise form-1 ... form-n) or (t form-1 ... form-n). Note that the syntax says {otherwise | t}. The vertical bar is an OR in a syntax specification. So the marker for an otherwise clause is either otherwise or t.
That means, if your case clause begins with otherwise or t, then we have an otherwise-clause.
In the case construct in Common Lisp, t, used by itself, is equivalent to default in C; that is, it's evaluated if the expression doesn't match any of the other cases. If you want to match the actual symbol t, use (t) instead.

Resources