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.
Related
This question already has an answer here:
My code signals the error "application: not a procedure" or "call to non procedure"
(1 answer)
Closed 4 years ago.
Sorry, I just started using racket. I'm pretty new at this. I've written this piece of code:
(define (save_sheets lst num)
(if(= num (- (length lst) 1))
('())
(
(my_save_image (join_sheet (list-ref lst num)) num)
(save_sheets lst (+ num 1)))))
Of course, when I run this I get this error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: (object:image% ...)
arguments...: [none]
(join_sheet (list-ref lst num)) should return an image, which the error shows, but the my_save_image should take it in right? It's parameters is the image and a number. Thanks!
Remember that parentheses in Racket (and other Lisp-like languages) are not like parentheses in other languages… they are important! In many languages, there is no difference between x, (x), ((x)), and ((((x)))), but in Racket, these are all very different expressions.
In Racket, parentheses mean function application. That is, (f) is like writing f() in other languages, so ((f)) is like writing f()(), and so on. This is important, since it means things like (3) are quite nonsensical in Racket—that would be like writing 3() in other languages, and 3 is definitely not a function.
Now, let’s consider the problem you’re having. You are using if, which has the following grammar:
(if conditional-expression then-expression else-expression)
This means that each of the pieces of code inside the if must be valid expressions on their own. However, take a close look at your then-expression, which is ('()). This is kind of like the (3) example from earlier, isn’t it? '() is not a function, so it should not be surrounded in parentheses!
Your else-expression exhibits a similar problem, but it is a little more complicated, since you seem to wish to run two functions there. If you want to run the first function for side-effects, you would not use parentheses alone for grouping, you would use begin, but it’s not clear to me if that’s what you actually want here or not. In any case, as-written, your program will attempt to apply the result of the call to my_save_image as a function, passing it the result of the recursive call to save_sheets as an argument, which is almost certainly not what you want.
Mind your parentheses. In Racket, they are to be treated with care.
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.
I have been programming in common lisp for a little while now, and throughout my experience using lisp, I have yet to see any function/macro that acts anything similar to function prototypes in C or C++.
Currently I have to very careful about the ordering of my functions, otherwise, when I try to call a function from another, Lisp says the function "does not exist" because it is defined later in the file. Is there a way to get around this? Can I declare all my function prototypes at the top of the file, and the full definitions below?
Declaim and Proclaim
You can use declaim to globally declare that a certain thing has a certain function type. For instance, look at what happens first if you define foo1 that calls undefined baz (in SBCL):
CL-USER> (defun foo1 ()
(baz))
; in: DEFUN FOO1
; (BAZ)
;
; caught STYLE-WARNING:
; undefined function: BAZ
;
; compilation unit finished
; Undefined function:
; BAZ
; caught 1 STYLE-WARNING condition
FOO1
Now, let's add a declamation that says that baz is a function of no arguments, and returns something. You could obviously add more type information if you wanted to, but this will at least provide the arity and the knowledge that baz is a function.
CL-USER> (declaim (ftype (function () t) baz))
; No value
Now when you define foo2 that also calls baz, you'll get no warning:
CL-USER> (defun foo2 ()
(baz))
FOO2
Declaim is a macro, but if you need to be able to generate some of these things at runtime, you can use proclaim, which is a function. E.g.,
CL-USER> (dolist (f '(square cube))
(proclaim `(ftype (function (number) number) ,f)))
NIL
CL-USER> (defun add-square-and-cube (x y)
(+ (square x) (cube y)))
ADD-SQUARE-AND-CUBE
That said, this is not very idiomatic Common Lisp. It's much more common to put the code you need into a file and then to compile that file and load it. If that's not possible for some reason, this will work, but it's worth considering other options of loading your code if they're available.
Muffling warnings
It's also worth noting that while SBCL will take the hint from proclaim or declaim and silence the undefined function warning, the function is still actually undefined. Other implementations (e.g., CLISP) will still issue a warning about the undefined function.
I don't really recommend the following approach, because warnings are around for a reason, but you can choose to muffle warnings when you evaluate code. E.g., in CLISP, we get a warning when we compile with undefined functions:
CL-USER> (compile nil (lambda () (baz)))
WARNING: Function BAZ is not defined
#<COMPILED-FUNCTION NIL>
1
1
We can bind a handler that will muffle any warnings that occur when the form is evaluated, though:
CL-USER> (handler-bind ((warning
(lambda (x)
(muffle-warning x))))
(compile nil (lambda () (baz))))
#<COMPILED-FUNCTION NIL>
1
1
This has its ow caveats, too, since the type of warning that you might get for compiling a reference to an undefined function might vary, and what muffling the warning does may vary.
As Rainer pointed out you can ignore this issue if the forward reference is within a single compilation unit. But that won't help if the forward reference crosses compilation units. Usually that's a sign that your code is poorly layered. Low level code makes calls to higher level code? Well, people will say the low level code is providing a hook for the high level code.
That said I certainly have seen and written code that had this problem. Spaghetti code, yum! It can arise when you start breaking huge source files into smaller ones. A compilation unit is usually a single file. But take a look at with-compilation-unit. I don't recall asdf doesn't provide easy access that though.
I don't know if Joshua's solution of using providing a declaration will work across all CL implementations. My memory is that when I had to solve this problem many many years ago we had to implement something more crude, we would give the function a stand in definition, and then hack together a way to suppress the definition warnings.
No doubt cl-launch could be used to see if Joshua's solution works across the spectrum of implementations.
You can define something to be a generic function before you define any of its methods. So, if you write
(defgeneric foo (x y z))
then any function calling FOO will see a defined function (although one without any methods). The body of the function can then be added later as a method
(defmethod foo (x y z)
;; The body of the function
...)
I have been programming in common lisp for a little while now, and throughout my experience using lisp, I have yet to see any function/macro that acts anything similar to function prototypes in C or C++.
Currently I have to very careful about the ordering of my functions, otherwise, when I try to call a function from another, Lisp says the function "does not exist" because it is defined later in the file. Is there a way to get around this? Can I declare all my function prototypes at the top of the file, and the full definitions below?
Declaim and Proclaim
You can use declaim to globally declare that a certain thing has a certain function type. For instance, look at what happens first if you define foo1 that calls undefined baz (in SBCL):
CL-USER> (defun foo1 ()
(baz))
; in: DEFUN FOO1
; (BAZ)
;
; caught STYLE-WARNING:
; undefined function: BAZ
;
; compilation unit finished
; Undefined function:
; BAZ
; caught 1 STYLE-WARNING condition
FOO1
Now, let's add a declamation that says that baz is a function of no arguments, and returns something. You could obviously add more type information if you wanted to, but this will at least provide the arity and the knowledge that baz is a function.
CL-USER> (declaim (ftype (function () t) baz))
; No value
Now when you define foo2 that also calls baz, you'll get no warning:
CL-USER> (defun foo2 ()
(baz))
FOO2
Declaim is a macro, but if you need to be able to generate some of these things at runtime, you can use proclaim, which is a function. E.g.,
CL-USER> (dolist (f '(square cube))
(proclaim `(ftype (function (number) number) ,f)))
NIL
CL-USER> (defun add-square-and-cube (x y)
(+ (square x) (cube y)))
ADD-SQUARE-AND-CUBE
That said, this is not very idiomatic Common Lisp. It's much more common to put the code you need into a file and then to compile that file and load it. If that's not possible for some reason, this will work, but it's worth considering other options of loading your code if they're available.
Muffling warnings
It's also worth noting that while SBCL will take the hint from proclaim or declaim and silence the undefined function warning, the function is still actually undefined. Other implementations (e.g., CLISP) will still issue a warning about the undefined function.
I don't really recommend the following approach, because warnings are around for a reason, but you can choose to muffle warnings when you evaluate code. E.g., in CLISP, we get a warning when we compile with undefined functions:
CL-USER> (compile nil (lambda () (baz)))
WARNING: Function BAZ is not defined
#<COMPILED-FUNCTION NIL>
1
1
We can bind a handler that will muffle any warnings that occur when the form is evaluated, though:
CL-USER> (handler-bind ((warning
(lambda (x)
(muffle-warning x))))
(compile nil (lambda () (baz))))
#<COMPILED-FUNCTION NIL>
1
1
This has its ow caveats, too, since the type of warning that you might get for compiling a reference to an undefined function might vary, and what muffling the warning does may vary.
As Rainer pointed out you can ignore this issue if the forward reference is within a single compilation unit. But that won't help if the forward reference crosses compilation units. Usually that's a sign that your code is poorly layered. Low level code makes calls to higher level code? Well, people will say the low level code is providing a hook for the high level code.
That said I certainly have seen and written code that had this problem. Spaghetti code, yum! It can arise when you start breaking huge source files into smaller ones. A compilation unit is usually a single file. But take a look at with-compilation-unit. I don't recall asdf doesn't provide easy access that though.
I don't know if Joshua's solution of using providing a declaration will work across all CL implementations. My memory is that when I had to solve this problem many many years ago we had to implement something more crude, we would give the function a stand in definition, and then hack together a way to suppress the definition warnings.
No doubt cl-launch could be used to see if Joshua's solution works across the spectrum of implementations.
You can define something to be a generic function before you define any of its methods. So, if you write
(defgeneric foo (x y z))
then any function calling FOO will see a defined function (although one without any methods). The body of the function can then be added later as a method
(defmethod foo (x y z)
;; The body of the function
...)
I have decided to learn (Common) Lisp a few days ago and I realize that this is quite a newbie question and it is probably extremely trivial to someone with at least a bit of experience.
So basically what happens is that I load up Emacs + Slime (via Lisp in a Box) and write my program (included below):
(defun last-char (s) "Get last character"
(char s (- (length s) 1)))
And then I try to compile it with C - c M - k, but then I get the following warning:
CHAR is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
What is the meaning of this warning? I suppose it might be something similar to forgetting #includes in C, but I can't quite figure it out. What should I do about it? Shall I just simply ignore it?
The warning means that char is not being recognized as a function, as it should, for some reason (it's reporting that the symbol is unbound, it has no value).
It might have something to do with your implementation. I've run your code using C-c M-k in my SBCL + Emacs/Slime (and in Clozure) and I get the following report from the compilation in SBCL:
; in: DEFUN LAST-CHAR
; (CHAR S (- (LENGTH S) 1))
; --> AREF
; ==>
; (SB-KERNEL:HAIRY-DATA-VECTOR-REF ARRAY SB-INT:INDEX)
;
; note: unable to
; optimize
; due to type uncertainty:
; The first argument is a STRING, not a SIMPLE-STRING.
;
; note: unable to
; avoid runtime dispatch on array element type
; due to type uncertainty:
; The first argument is a STRING, not a SIMPLE-ARRAY.
Try just typing
#'char
on the REPL, the response should be that it is reported to be a function,
CL-USER> #'char
#<FUNCTION CHAR>
but maybe it doesn't in your implementation (I'm guessing it doesn't, given the compiler warning and the fact that the code compiles correctly in SBCL). If that's the case, then that is a point where your implementation departs from the ANSI Common Lisp specification, because that function should be there.
Just a note regarding your indentation. Here's a more conventional indentation:
(defun last-char (s)
"Get last character"
(char s (- (length s) 1)))