I'm using the sketch library on this function:
(defun init-plot (&optional (title "Plot Window")
(x-size 250) (y-size 250))
(defsketch window ((width x-size)(height y-size)(title title)))
(make-instance 'window ))
Basically is a three optional arguments function, that make a class sketch a create a instance. the function works but it has this warning:
; In INIT-PLOT: Unused lexical variable TITLE
with this, the title option doesn't work, but this variables are on different scopes, so I do not get why I have to change the name of the first variable. because whithout changing it does not work
defscket is a macro that wraps defclass
(defmacro defsketch (sketch-name bindings &body body)
...
So I don't get the point what is happening here
Related
I am trying to define a macro that creates commands. So far I have the following:
(defmacro create-command (command name)
`(defcommand ,name ()
(run-shell-command ,command)
))
(create-command "firefox" firefox)
Basically, I want to create a command that called "firefox", that simply launches "firefox". When I try to run the command I get the following error:
Bad Argument Type: RUN-SHELL-COMMAND.
Any idea on what is happening? Thank you!
defcommand has two argument lists, not once; the second list defines how arguents in the first list are read interactively. In your case there is no arguments, but you missed one empty list:
(defmacro create-command (command name)
`(defcommand ,name () ()
(run-shell-command ,command)))
STUMPWM-USER> (create-command "firefox" firefox)
#S(STUMPWM::COMMAND :NAME FIREFOX :CLASS T :ARGS 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.
I have never been able to come up with a method to penetrate the set-process-sentinel hierarchy with let-bound variables defined at the outset of the function -- only buffer-local or global variables can penetrate it. Let-bound variables can reach the first start-process, but that is as far as they can penetrate without being rejected due to being unrecognized -- let-bound variables defined at the outset of the function do not appear to be able to penetrate the section that begins with (lambda (p e) . . .. Can anyone think of a way to do it, including penetrating nested sentinels like in the example below?
(set-process-sentinel
(start-process
"my-process-name-one"
"*OUTPUT-BUFFER*"
"/path/to/executable"
"argument-one"
"argument-two"
"argument-three")
(lambda (p e) (when (= 0 (process-exit-status p))
(set-process-sentinel
(start-process
"my-process-name-two"
nil ;; example of not using an output buffer
"/path/to/executable"
"argument-one"
"argument-two"
"argument-three")
(lambda (p e) (when (= 0 (process-exit-status p))
(set-process-sentinel
(start-process . . . ))))))))
The problem is that Emacs Lisp variable bindings are dynamic by default. That is, when a function is evaluated, bound variables are looked up not in the environment where the function was defined, but in the environment where the function was called.
Emacs 24 or later supports lexical binding (that is, the function sees the variables that were bound around the function definition) natively, but since it alters the semantics of existing code you need to enable it explicitly. Usually this is done by adding a file local variable setting to the first line of the .el file:
;; -*- lexical-binding: t; -*-
Another alternative is to use lexical-let from the cl library. This works in earlier Emacs versions as well. Note that in this way you explicitly specify which variables should have lexical binding, so code such as (lexical-let ((foo foo)) ...) is not uncommon — foo is an existing variable which needs to be "carried over" into the function.
The following is an example using dynamic bindings:
(defun example-dynamic-fn ()
"Doc-string"
(interactive)
(let ((test-variable "Hello-world!"))
(set-process-sentinel
(start-process "process-one" "*one*" "echo" test-variable)
`(lambda (p e) (when (= 0 (process-exit-status p))
(set-process-sentinel
(start-process "process-two" "*two*" "echo" ,test-variable)
'(lambda (p e) (when (= 0 (process-exit-status p))
(start-process "process-three" "*three*" "echo" ,test-variable)
(set-process-sentinel
(start-process "process-four" "*four*" "echo" ,test-variable)
'(lambda (p e) (when (= 0 (process-exit-status p))
(set-process-sentinel
(start-process "process-five" "*five*" "echo" ,test-variable)
'(lambda (p e) (when (= 0 (process-exit-status p))
(message "test-variable: %s" ,test-variable)))))))))))))))
OK, I think I've got this now. The link above provides a good example; here's another in case anyone else has this difficulty:
;;; ensure VAR1 has no binding
(makunbound 'VAR1)
;;;
(defun f1 (&optional VAR1)
(interactive)
(unless VAR1
(set 'VAR1 "variable1"))
(pop-to-buffer "*test*")
; (lexical-let ( (VAR1 VAR1) ) ;;;
(set-process-sentinel
(start-process-shell-command "test"
"*test*"
(concat "echo " VAR1))
(lambda (process event)
(condition-case err
(when (string-match-p "finished" event)
(f2 VAR1))
(error
(princ
(format "Sentinel error: %s" err))))))
; ) ;;;
)
;;;
(defun f2 (&optional VAR2)
(interactive)
(unless VAR2
(set 'VAR2 "VARIABLE2"))
(print VAR2))
We load everything (with the lines in (f1) commented out) and run (f1). The value of VAR1 is passed to (f2) before the error occurs. The error (void-variable VAR1) appears to come from the scoping environment of (set-process sentinel PROCESS SENTINEL); VAR1 is not defined there even though it remains in scope for the SENTINEL ((lambda)) function.
Also using (set ) as above is not best practice when a variable is only meant to have scope local to the function.
If we uncomment the lines marked with ; then everything works as expected. Happily, we can pass the value through to another function, which prevents a long series of (set-process sentinel )s building up. It also allows us to generate processes with additional sub-processes, if required.
One of my mistakes was naming the SENTINEL as a discrete function, rather than keeping it inside the (lexical-let ) function. While the lexical-binding: t; approach is attractive, it will tend to break working code which relies on the standard (let ).
Test #1
I have a globally declared variable f, and a function with argument named f:
(defvar f 1)
(defun test (f)
f)
I call the function and it returns the value of the argument:
(test 2)
=> 2
Test #2
I again have a globally declared variable f, and a function with argument named f. This time, however, the function returns a lambda, which returns f:
(defvar f 1)
(defun test (f)
#'(lambda ()
f))
I call the function and it returns the lambda function. Then I call the lambda function and it returns the value of the global f:
(funcall (test 2))
=> 1
I am surprised. I thought the lambda function is a closure and would return the local f, not the global f. How do I modify the test function and/or the lambda function so that the lambda function returns the local f, not the global f?
A pointer to an online resource that discusses this particular scoping issue would be appreciated.
By using defvar you are declaring f a special (aka dynamically bound) variable. f in your code from there on are no longer lexically closed but in fact the same as the global variable momentarily changed to 2.
Because of this feature lispers are not happy about global variables without their *earmuffs*. Once they have *earmuffs* it's much easier to see it:
(defvar *f* 1) ; special variable *f*
(defun test (*f*) ; momentarily rebind *f*
(format nil "*f* is ~a~%" *f*) ; use new value
#'(lambda () ; return lambda using *f*
*f*)) ; *f* goes back to being 1
(funcall (test 2)) ; ==> 1 (prints "*f* is 2\n")
So the lesson is: Never make global variables without *earmuffs* since you will get crazy runtime errors which are almost impossible to detect. This naming convention isn't just for fashion!
As for documentation the hyperspec actually shows how dynamic variables work in the examples for defparameter and defvar. See that they call (foo) => (P V) and that foo re-binds *p* and *v* during its call to bar and, since they are dynamically bound, bar uses the altered values.
Question: How to force a s-exp to be evaluated before passing to a function expecting parameter of string type or else.?
This code is fine (no error):
(setf (slot-value (ole sheet :range "A1:B1") 'value)
`(("123" "456"))))
However, when passing a s-exp such as (first line) instead of "123":
(setf line '("123" "456"))
(setf (slot-value (ole sheet :range "A1:B1") 'value)
`(((first line) (second line)))))
There is error message:
The value FIRST is not of the expected type (OR
STRING
FIXNUM
SINGLE-FLOAT
DOUBLE-FLOAT).
[Condition of type TYPE-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [ABORT-BREAK] Reset this thread
3: [ABORT] Kill this thread
I know what the problem is. But is there way get rid of this restriction? Because we would need to put the line of code inside a loop, so can't fix the parameter value to such as "123"...
I try using macro:
(defmacro set-line (par1 par2)
`(setf (slot-value (ole sheet :range "A1:B1") 'value)
`((,par1 ,par2))))
However, it doesn't work. Still the same error message saying the wrong type (first line)...
(set-line (first line) (second line))
Also I don't know how to escape the backquote ` if it appears inside macro body. I have tried put a \ in front of backquote inside the macro body, but then the \ would also appear upon macro expand.
`(setf xxx ` <--- another backquote
`(setf xxx \` <--- this can't escape backquote inside macro body
Thanks.
Background: when playing with Win32 OLE Excel example in:
https://github.com/quek/cl-win32ole/blob/master/example/excel.lisp
You are missing the basics of quotation. Your expression
? `(("123" "456")) ; quasiquote
(("123" "456"))
is a list containing a list and can also be created using the function LIST as
? (list (list "123" "456")) ; list
(("123" "456"))
To use expressions, you can either use unquote (note the preceding comma)
? `((,(first line) ,(second line))) ; quasiquote with unquote
(("123" "456"))
or, better
? `(,line)
(("123" "456"))
or use list :
? (list line)
(("123" "456"))