Starting REPL clisp-2.49-r8:
clisp -K full
Trying to execute something from DBUS module test
http://clisp.cvs.sourceforge.net/viewvc/clisp/clisp/modules/dbus/test.tst
(listp (show (multiple-value-list (ext:module-info "dbus" t)) :pretty t))
Getting:
*** - EVAL: undefined function SHOW
Where I can find this SHOW function?
Sorry...
It was defined in tests/tests.lisp
(defun show (object &key ((:pretty *print-pretty*) *print-pretty*))
"Print the object on its own line and return it. Used in many tests!"
(fresh-line) (prin1 object) (terpri) object)
Related
I want to create an interpreted function definition, not a compiled one.
SBCL manual says :
Variable: *evaluator-mode* [sb-ext] : Toggle between different evaluator
implementations. If set to :compile, an implementation of eval that
calls the compiler will be used. If set to :interpret, an interpreter
will be used.
So, I try to create a BAR function (which does not exist) :
(let ((sb-ext::*evaluator-mode* :interpret))
(defun bar (x) (+ x 1)))
But then, I check, and BAR is already compiled :
CL-USER> (compiled-function-p #'bar)
T
So, how do you create an interpreted version of BAR ?
The let form in your question only sets the evaluator mode at runtime. By then, the function has already been compiled.
You need to set it at load time and also make sure to load the file instead of compiling then loading it.
Try this:
In your-file.lisp:
;; at load time, set evaluator mode to interpret (before bar definition is met)
(eval-when (:load-toplevel :execute)
(setf sb-ext::*evaluator-mode* :interpret))
;;define your interpreted function
(defun bar (x)
(+ x 1))
;; set evaluator back to compile mode (optional)
(eval-when (:load-toplevel :execute)
(setf sb-ext::*evaluator-mode* :compile))
;;check if bar is a compiled function
(print (compiled-function-p #'bar)) ;;prints NIL
Then load it with (load "your-file.lisp") (this doesn't compile the file first).
I think that *evaluator-mode* is pretty inherently a global variable. For instance, if you do this:
> (setf sb-ext:*evaluator-mode* ':interpret)
:interpret
> (setf (symbol-function 'bar)
(lambda (x) x))
#<interpreted-function nil {10026E7E2B}>
> (compiled-function-p #'bar)
nil
you get an interpreted function. But if you do this:
> (setf sb-ext:*evaluator-mode* ':compile)
:compile
> (setf (symbol-function 'bar)
(let ((sb-ext:*evaluator-mode* ':interpret))
(lambda (x) x)))
#<function (lambda (x)) {52C3687B}>
> (compiled-function-p #'bar)
t
You don't. My take on this, which may be wrong, is that the value which is in effect at the start of each top-level form is what counts: once the system has decided that it's going to use the compiling-evaluator for a form then it can't change its mind.
And note that there is a complicated definition of 'top-level form', and in particular that when processing a file then in a form like
(let (...)
(x ...))
then (x ...) is not a top-level form.
I'm still quite new to Common Lisp macros.
For an abstraction over a defclass with defgeneric I thought it'd be nice to make a macro.
A complitely naive implementation looks like:
(defmacro defgserver (name &key call-handler cast-handler)
"TODO: needs firther testing. Convenience macro to more easily create a new `gserver' class."
`(progn
(defclass ,name (gserver) ())
(defmethod handle-call ((server ,name) message current-state)
,(if call-handler call-handler nil))
(defmethod handle-cast ((server ,name) message current-state)
,(if cast-handler cast-handler nil))))
When used the error says that 'message' is not known.
I'm not sure. 'message' is the name of a parameter of defgeneric:
(defgeneric handle-call (gserver message current-state))
Using the macro I see a warning 'undefined variable message':
(defgserver foo :call-handler
(progn
(print message)))
; in: DEFGSERVER FOO
; (PRINT MESSAGE)
;
; caught WARNING:
; undefined variable: COMMON-LISP-USER::MESSAGE
Which when used has this consequence:
CL-USER> (defvar *my* (make-instance 'foo))
*MY*
CL-USER> (call *my* "Foo")
<WARN> [10:55:10] cl-gserver gserver.lisp (handle-message fun5) -
Error condition was raised on message processing: CL-GSERVER::C: #<UNBOUND-VARIABLE MESSAGE {1002E24553}>
So something has to happen with message and/or current-state.
Should they be interned into the current package where the macro is used?
Manfred
The problem, as mentioned, is that you are talking about different symbols.
However this is really a symptom of a more general problem: what you are trying to do is a sort of anaphora. If you fixed up the package structure so this worked:
(defgserver foo :call-handler
(progn
(print message)))
Then, well, what exactly is message? Where did it come from, what other bindings exist in that scope? Anaphora can be useful, but it also can be a source of obscure bugs like this.
So, I think a better way to do this, which avoids this problem is to say that the *-handler options should specify what arguments they expect. So instead of the above form you'd write something like this:
(defgserver foo
:call-handler ((server message state)
(print message)
(detonate server)))
So here, value of the :call-handler-option is the argument list and body of a function, which the macro will turn into a method specialising on the first argument. Because the methods it creates have argument lists provided by the user of the macro there's never a problem with names, and there is no anaphora.
So, one way to do that is to do two things:
make the default values of these options be suitable for processing into methods without any special casing;
write a little local function in the macro which turns one of these specifications into a suitable (defmethod ...) form.
The second part is optional of course, but it saves a little bit of code.
In addition to this I've also done a slightly dirty trick: I've changed the macro definition so it has an &body option, the value of which is ignored. The only reason I've done this is to help my editor indent it better.
So, here's a revised version:
(defmacro defgserver (name &body forms &key
(call-handler '((server message current-state)
(declare (ignorable
server message current-state))
nil))
(cast-handler '((server message current-state)
(declare (ignorable
server message current-state))
nil)))
"TODO: needs firther testing. Convenience macro to more easily
create a new `gserver' class."
(declare (ignorable forms))
(flet ((write-method (mname mform)
(destructuring-bind (args &body decls/forms) mform
`(defmethod ,mname ((,(first args) ,name) ,#(rest args))
,#decls/forms))))
`(progn
(defclass ,name (gserver) ())
,(write-method 'handle-call call-handler)
,(write-method 'handle-cast cast-handler))))
And now
(defgserver foo
:call-handler ((server message state)
(print message)
(detonate server)))
Expands to
(progn
(defclass foo (gserver) nil)
(defmethod handle-call ((server foo) message state)
(print message)
(detonate server))
(defmethod handle-cast ((server foo) message current-state)
(declare (ignorable server message current-state))
nil))
I have added the following method to the generic function speak but would now like to remove this particular method in the REPL without removing the rest of the generic functions' methods.
(defmethod speak :around ((c courtier) string) ; [1]
(format t "Does the King believe that ~A?" string)
(if (eql (read) 'yes)
(if (next-method-p) (call-next-method)) ; [2]
(format t "Indeed, it is a preposterous idea.~%"))
'bow)
[1] The :around method replaces the primary method for the type.
[2] Then it decides whether to call the primary method or not.
The documentation link to the function remove-method has no examples and I don't know what is the syntax to refer to the actual :around method above.
(remove-method #'speak)
TOO FEW ARGUMENTS
(remove-method #'speak :around)
NO-APPLICABLE-METHOD
From the documentation:
remove-method generic-function method
It expects a generic function object and a method object as arguments.
One can find the method via find-method.
CL-USER 39 > (find-method #'speak
(list :around)
(list (find-class 'courtier) (find-class t)))
#<STANDARD-METHOD SPEAK (:AROUND) (COURTIER T) 42001285EB>
CL-USER 40 > (remove-method #'speak
(find-method #'speak
(list :around)
(list (find-class 'courtier)
(find-class t))))
#<STANDARD-GENERIC-FUNCTION SPEAK 422000A68C>
Note also that a good Lisp development environment may also allow to remove methods in the editor or the inspector.
Note that in the Lisp listener, one does not need to call find-method twice like above. The variable * contains the last result.
CL-USER 43 > (find-method #'speak
(list :around)
(list (find-class 'courtier)
(find-class t)))
#<STANDARD-METHOD SPEAK (:AROUND) (COURTIER T) 4200150DEB>
CL-USER 44 > (remove-method #'speak *)
#<STANDARD-GENERIC-FUNCTION SPEAK 422000A68C>
Here is another interaction example using SLIME in GNU Emacs with the presentation feature for SLIME enabled. A presentation is Lisp output, which keeps the connection between the printed object and the generated text.
Call the find-method function. It returns the method. Here we use presentations, which keep the connections between text and Lisp objects. The output is displayed in the color red and it is mouse-sensitive. Moving the mouse over the red returned object will add interaction options.
Now type (remove-method #'speak and then middle-click (or whatever SLIME is configured to use) on the red output: the presentation (the text and the connected object) will be copied to the line. Type ) and enter the form. SLIME has actually constructed a list with the real object and not the textual representation, then.
This is how repls work on the Symbolics Lisp Machine and in CLIM / McCLIM...
If using GNU Emacs with SLIME, you can also use slime-inspector. For example define generic function foo and two methods:
USER> (defgeneric foo (x))
#<STANDARD-GENERIC-FUNCTION FOO (0)>
USER> (defmethod foo ((x string)) (length x))
#<STANDARD-METHOD FOO (STRING) {100B4D7E23}>
USER> (defmethod foo ((x integer)) x)
#<STANDARD-METHOD FOO (INTEGER) {100C355843}>
You have two main options to enter the inspector:
From the REPL, type #'foo so that a presentation object for the generic method is printed:
USER> #'foo
#<STANDARD-GENERIC-FUNCTION FOO (0)>
Either right-click the presentation (anywhere inside #<...>) and select Inspect, or put the cursor in the presentation and press C-c C-v TAB (slime-inspect-presentation-at-point).
From a source file, enter slime-inspect, a.k.a. C-c I, and enter #'foo.
In both cases, you are shown a view similar to this:
#<STANDARD-GENERIC-FUNCTION {505A9A2B}>
--------------------
Name: FOO
Arguments: (X)
Method class: #<STANDARD-CLASS COMMON-LISP:STANDARD-METHOD>
Method combination: #<SB-PCL::STANDARD-METHOD-COMBINATION STANDARD () {1000214003}>
Methods:
(INTEGER) [remove method]
(STRING) [remove method]
(....)
Each [remove method] text is actually a button, click or press Return on any of them to remove the associated method from the generic function.
Given
(defun show-arg (a)
(format t "a is ~a~%" a))
(defun show-key (&key a)
(format t "a is ~a~%" a))
evaluating
(show-arg)
will lead to an error saying "invalid number of arguments: 0", where
(show-key)
will display a is NIL
How can I get SHOW-KEY to signal an error like SHOW-ARG does? Is there a way other than using (unless a (error "a is required")) in the function body? I am very fond of keyword arguments and use them constantly, and almost always want them to be required.
Keyword arguments are always optional, so you do need to manually check if they're given and signal an error if needed. It would be better to not require keyword arguments though. The compiler won't recognize them as required and thus won't given you an error message for missing arguments at compile time.
If you do want to require them, you can specify the arguments with a three element list; the first element being the argument, the second is the default value and the third is a variable that will be true if the argument was given. Checking the third element is better than checking the keyword itself, because then you can tell the difference between a NIL that was the default, and a NIL that the user gave as an argument.
(defun foo (&key (keyarg nil keyargp))
(unless keyargp (error "KEYARG is required."))
(* keyarg 2))
Edit
Now that I think about this a bit more, there actually is a way to get compile time errors for missing keyword arguments. Define a compiler macro for the function:
(defun foo (&key a b c d)
(* a b c d))
(define-compiler-macro foo (&whole whole &key (a nil ap) (b nil bp)
(c nil cp) (d nil dp))
(declare (ignore a b c d))
(unless (and ap bp cp dp)
(error "Missing arguments..."))
whole)
One possibility would be:
(defun foo (&key (arg1 (error "missing arg1 in call to function foo")))
arg1)
Using it:
CL-USER 80 > (foo)
Error: missing arg1 in call to function foo
1 (abort) Return to level 0.
2 Return to top loop level 0.
This will give an error at runtime, unfortunately not at compile time.
I'm getting a warning from the sbcl compiler, that a variable has been defined but is not used. And the compiler is right. I want to get rid of the warning, but don't know how to do it. Here is an example:
(defun worker-1 (context p)
;; check context (make use of context argument)
(if context
(print p)))
(defun worker-2 (context p)
;; don't care about context
;; will throw a warning about unused argument
(print p))
;;
;; calls a given worker with context and p
;; doesn't know which arguments will be used by the
;; implementation of the called worker
(defun do-cmd (workerFn context p)
(funcall workerFn context p))
(defun main ()
(let ((context ()))
(do-cmd #'worker-1 context "A")
(do-cmd #'worker-2 context "A")))
The do-cmd-function expects worker-functions that implement a specific interface f(context p).
The sbcl compiler throws the following warning:
in: DEFUN WORKER-2
; (DEFUN WORKER-2 (CONTEXT P) (PRINT P))
;
; caught STYLE-WARNING:
; The variable CONTEXT is defined but never used.
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
You need to declare that the parameter is intentionally ignored.
(defun worker-2 (context p)
(declare (ignore context))
(print p))
ignore will also signal a warning if you do use the variable. To suppress warnings in both cases, you can use the declaration ignorable, but this should only be used in macros and other such cases where it's not possible to determine whether the variable will be used at the point of its declaration.
In case you are not yet familiar with declare, note that it is not an operator, and instead can only appear in certain locations; in particular, it must be located before all forms in the defun body, though it can be either above or below a documentation string.