So I have been trying to learn Lisp lately. Unfortunately, nothing seems to work - I am following this Common Lisp tutorial but when I tried to run (hello-world) a second time, instead of doing the same thing it gave me an error (Which I lost, because I didn't think to save it) about how CL-USER> was an undefined variable. I have never typed CL-USER> into SLIME, but that IS what the prompt is. I restarted EMACS and SLIME (Closed the window, that is) and restarted it. However, upon tryig to use the (load "name") method, it gave me the following error:
Compiler warnings for "helloworld.cl" :
; In an anonymous lambda form at position 43: Undeclared free variable CL-USER>
; In an anonymous lambda form at position 52: Undeclared free variable CL-USER>
; In an anonymous lambda form at position 58: Undeclared free variable ..\sOURCECODELISP\hELLOWORLD.CL
; In an anonymous lambda form at position 161: Undeclared free variable CL-USER>
; In an anonymous lambda form at position 278: Undeclared free variable CL-USER>
; In an anonymous lambda form at position 389: Undeclared free variable CL-USER>
Read error between positions 441 and 450 in f:/Lispbox/helloworld.cl.; Evaluation aborted on #<SIMPLE-ERROR #x2100B925AD>.
How can I fix it?
EDIT: After closing it, going to my next few classes, then staying after school, the problem persists, but now it just complains that CL-USER> is not a defined variable.
FYI, I originally attempted to load my file from ..\sourcecode\Lisp\helloworld.cl because that's where I put it at first. I forgot quotes around it, so that may have caused the problem.
When you copied code from an interactive session to the file helloworld.cl, you should have removed the prompts and interaction messages.
Related
I'm trying to get a better understanding of how S-expressions are evaluated in different lisps and wanted to see they would handle interesting ill-formed expressions. I get that Common Lisp and Scheme are totally different languages, but is there a specific difference in their semantics that explains the difference in behavior. For example, Lisp-1s and Lisp-2s have observable differences in their behavior, as do hygienic vs non-hygienic macro systems.
I have a program containing an unreachable ill-formed if expression in Scheme and Common Lisp.
;; foo.scm
(if #t 1 (if))
(display "12")
And the Common Lisp version
;; foo.lisp
(if t 1 (if))
(display "12")
chicken and guile both produce a syntax error.
Chicken:
% chicken foo.scm
Syntax error: (foo.scm:1) in `if' - pair expected
(if)
Expansion history:
<syntax> (##core#begin (if #t 1 (if)))
<syntax> (if #t 1 (if))
<syntax> (##core#if #t 1 (if))
<syntax> (if) <--
Guile:
% guile foo.scm
...
.../foo.scm:1:9: source expression failed to match any pattern in form (if)
sbcl and clisp both print 12 and emit no warnings.
SBCL:
% sbcl --load foo.lisp
This is SBCL 1.3.11, an implementation of ANSI Common Lisp.
...
12
0]^D
CLISP
% clisp foo.lisp
"12"
Implementations of Common Lisp: Interpreter and Compilers
In Common Lisp the type of code execution depends on what the Lisp system implements and how you use it. Often Common Lisp implementations have multiple ways to execute code: an interpreter and one or more compilers. Even a single running implementation may have that and it will allow the user to switch between those.
Interpreter: executing directly from the Lisp data structure. It is not an interpreter of virtual machine code, like the JVM. One would not expect that the interpreter validates the full code tree/graph during execution. The interpreter usually looks only at the current top form it executes.
Compiler: compiles Lisp code to C, some Byte Code or Machine Code. Since the compiler generates code before the code runs, it will do a syntax check of all the code (for a possible exception, see the remark at the bottom) it sees.
Toplevel evaluation: may use an interpreter, a compiler or a mix of both.
GNU CLISP has both an interpreter and a compiler
Example in GNU CLISP:
LOAD of a text file typically uses the interpreter:
[1]> (load "test.lisp")
;; Loading file test.lisp ...
;; Loaded file test.lisp
T
The Interpreter will not detect the error, because it does not check the whole expression for syntactic correctness. Since the else clause with the syntax error is never used, the Interpreter will never look at it.
CLISP also has a compiler:
[2]> (compile-file "test.lisp")
;; Compiling file /tmp/test.lisp ...
** - Continuable Error
in #:|1 1 (IF T 1 ...)-1| in line 1 : Form too short, too few arguments: (IF)
If you continue (by typing 'continue'): Ignore the error and proceed
The following restarts are also available:
ABORT :R1 Abort main loop
As you see, the CLISP compiler detects the syntax error and gives a clear error message.
SBCL uses a compiler, but also has an interpreter
SBCL by default uses a compiler, which will detect the error. For top-level forms it uses for some forms a simpler evaluation mechanism. One can also switch to an interpreter.
If you write a simple IF form in SBCL, the evaluator does not use full compilation and doesn't catch the error:
CL-USER> (if t 1 (if))
1
If you write the same code inside a function definition, the error gets detected, because function definitions will be compiled by default:
CL-USER> (defun foo () (if t 1 (if)))
; in: DEFUN FOO
; (IF)
;
; caught ERROR:
; error while parsing arguments to special operator IF:
; too few elements in
; ()
; to satisfy lambda list
; (SB-C::TEST SB-C::THEN &OPTIONAL SB-C::ELSE):
; between 2 and 3 expected, but got 0
;
; compilation unit finished
; caught 1 ERROR condition
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
If you would switch to the full SBCL interpreter, the error would not be detected at definition time:
CL-USER> (setf *evaluator-mode* :interpret)
:INTERPRET
CL-USER> (defun foo () (if t 1 (if)))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
Optimisation and syntax checking
Note that some optimising compilers might not check the syntax of unreachable code.
Summary
In most Common Lisp implementations you need to use the compiler to get full syntax warnings/errors.
Looks like the CL part is handled by nicely by Rainer. I just want to point out that R5RS are not required to act the way as your two implementations are.
R5RS is very underspecified and for if it only specifies what to do when used right we have this passage about error handling:
When speaking of an error situation, this report uses the phrase "an
error is signalled" to indicate that implementations must detect and
report the error. If such wording does not appear in the discussion
of an error, then implementations are not required to detect or report
the error, though they are encouraged to do so. An error situation
that implementations are not required to detect is usually referred to
simply as "an error."
So, to wrap this up in R5RS the string "banana" is just as correct as Guile and Chickens response to the evaluation of (if #t 1 (if)).
R6RS on the other hand states in general that when an exceptional situation is detected by the implementation, an exception is raised. This means that if with less than two expressions or more than 3 should raise an exception, but it doesn't say it has to happen compile time since the language might be parsing and interpreting as it goes.
Why won't this compile? Why does it come up saying that ordered is an undefined function?
(defun ordered (numbers)
(sort numbers #'<))
(defun printing-ordered (numbers)
(princ (apply #'ordered numbers)))
I am using SBCL, and Emacs with SlIME.
The error I get when compiling is:
; compilation unit finished
; Undefined function:
; ORDERED
; caught 1 STYLE-WARNING condition
Running the same bits of code in my Emacs-Slime-SBCL combo gives expected results - a condition with message "invalid numbers of arguments". Try evaluating the first defun first if it helps at all. A bit mysterious indeed.
As side commentary; just as #Sylwester did, I noticed that you may have mixed funcall and apply together. The latter "unpacks" a list argument into several separate arguments while the former just passes on the given arguments as-is.
Byte compiling emacs lisp is pretty useful, as it generates compiler warnings that, though sometimes cryptic, always point at an error or unfinished tasks, such as missing imports or unimplemented functions.
However, I cannot find a way to generate custom compiler-warnings that integrate well with the *Compile-Log* buffer, i.e. that show the position of the error like
mymodule.el:247:1:Warning: Unused lexical variable `file-name'
E.g. I'm using the subsequent code for placing todo items that raise compile-time messages:
(eval-when-compile
(defmacro TODO (string)
`(eval-when-compile
(message "TODO: %s" ,string))))
However, I cannot find a way to add information (at compile-time) on
file name
line-number
At load-time the variable load-file-name is available, but it is nil at compile-time. The variable default-directory is defined at compile-time but doesn't help in this case.
For the line-number I know no method at all.
When using (warn ...) instead, I get something like
Warning (emacs): TODO: Complete or remove
i.e. no position information at all. If I use (error ...), I get the line number etc displayed automatically, but compilation stops instead of showing all errors and warnings, so it is not a viable solution either.
Update
A partial solution seems to be
(funcall (if byte-compile-current-file 'byte-compile-warn 'warn) FORMAT [ARGS ...])
You need to use the internal variables byte-compile-current-file (the name of the file being compiled) and byte-compile-read-position (the character position at the start of the last read).
Alternatively, you can try the function byte-compile-warning-prefix which inserts the file:line prefix in the *Warnings* buffer.
Either way, you are on your own, messing with the Emacs internals; SO is your only friend. :-)
Indeed, that was a problem. And even byte-compile-read-position is fairly poor because it's not yet up-to-date when the macro is expanded. In Emacs's trunk there is macroexp--warn-and-return, tho as the -- implies, it's currently still considered internal. E.g.
(defmacro TODO (string)
(macroexp--warn-and-return
(format "TODO: %s" string)
nil))
To understand how to use it, you have to understand that it works by returning a special piece of code which makes the byte-compiler later on (when the line-info is available) emit the message.
How do you go about solving this problem?
Suppose I want to write a function that does the following: if the user has library X installed, then use function X-function, otherwise - skip?
What I tried:
(when (symbol-function 'X-function)
(X-function))
I'm getting a warning for this code - so what is the right way?
How about this:
(when (fboundp 'X-function)
(X-function))
The docs at http://www.gnu.org/software/emacs/manual/html_node/elisp/Function-Cells.html says about symbol-function
If the symbol's function cell is void, a void-function error is signaled.
I'm guessing that is what you are seeing. On the other hand, fboundp just returns t or nil depending on whether the function exists.
The way to suppress this compiler warning is with something like:
(declare-function X-function "ext:X-library.el")
(when (fboundp 'X-function)
(X-function))
Here X-library is the name of the library that X-function is defined in when the library is there. The byte-compiler will then do the following:
It will look for the library in the load path.
If it finds it, it will check that the function has been defined.
If it does not find the library it will assume that it will be when the library is there and pass on without error.
Thus if there is no X-library it won't complain, but if there is one and it does not define the function then it will. This means that if an updated version of the library does not contain X-function then you will know when you try to re-compile your code.
If you look up the documentation for declare-function you will find that it can also check the argument list of functions.
Incidentally If you get similar warnings about undeclared variables you can suppress these with:
(defvar X-variable)
However it is important not to set the variable even if you know what value the library sets it to as this could change in a later version.
This gives you one version of the program that works whether or not X-library is present. You might prefer to have two versions, one for when X-library is present and one for when it is not. This can be done with a macro:
(defmacro run? (function &rest args)
"Expand to function call if function exists."
(when (fboundp `,function)
`(,function ,#args)))
Now instead of a call like:
(X-function a1 a2 a3)
You write:
(run? X-function a1 a2 a3)
If you compile it with X-library present this expands to the call to X-function. If the library is not present then it expands to nothing at all. You will not need the declare-function in any case. This gives two different versions, but it should be more efficient because the decisions as to whether the library is there or not are taken at compile time not run time.
One small caveat. If you go for this second solution you must either compile the whole program in the X-library environment or outside it. If you try loading the library half way through the program then when interpreted it will work as you might expect with the macro expanding differently before and after the load. But in a compiled program a macro is only expanded once. The test test for the library is in code that does the expanding not in the expansion, so the macro will not work the same before and after the load.
Another case when you can get the warning that a function cannot be found is when you define a function programmatically and use fset to set it. The following example illustrates this and what to do about it:
(eval-and-compile
(fset 'my-function1 (lambda () nil)))
(my-function1)
(fset 'my-function2 (lambda () nil))
(my-function2)
(my-function3)
(eval-and-compile
(fset 'my-function3 (lambda () nil)))
If you compile this you get the warnings:
Warning: the function `my-function2' is not known to be defined.
and:
Warning: the function `my-function3' might not be defined at runtime.
The second warning goes away if you re-compile the code a second time in the same Emacs session, but the first doesn't.
What is happening here is this: When the compiler sees eval-and-compile, it first evaluates the body of the in the current Emacs session and then compiles it. Having evaluated the code, Emacs knows about the programmatically defined function.
In the case of function1, the byte compiler sees the function call after Emacs has evaluated the form and so you don't get any warnings.
In the case of function2 the byte compiler never knows the functions is defined so you always get a warning.
In the case of function3, the first time round, the bite compiler doesn't know the function exists when it sees the function call. By the end of the compilation it knows the function exists but it isn't intelligent enough to work out how it knows so you get a different warning. However, if you re-compile it in the same Emacs session, it does know so the warning goes away.
Note that eval-and-compile, like eval-with-compile, look like a progn to the Emacs interpreter.
Good day, when load any source file into editor i get following message:
File mode specification error: (wrong-type-argument stringp nil)
and flymake simply not working then.
Starting with --init-debug does not improve anythong. Any idea how to debug the cause of problem ?
This general error is thrown when a Lisp function actually expects a string argument but receives a nil.
Try setting (setq debug-on-error t) at the top of your .emacs to get a stack-trace showing you which string is nil. In case the error is caused by FlyMake settings in your .emacs: here is a good introduction.
The deeper reason for wrong-type-argument exceptions is that Lisp functions have no prototypes and cannot rely on the interpreter; they're always defined and hence need to parse their arguments on their own.
The Emacs Lisp interpreter itself does not perform type checking on
the actual arguments passed to functions when they are called. [...]
It is therefore up to the individual function to test whether each
actual argument belongs to a type that the function can use.
For more information see Type Predicates in the Emacs Lisp Reference Manual.