String converted to a function command for global-set-key (elisp) - string

I would like to call global-set-key in a function, giving it arguments, to create global-set-keys.
(defun global-setter (arg1 arg2)
(global-set-key arg1 '(concat "example" arg1 arg2))
)
(global-setter "*" "^")
This should create the binding that when pressing *, the function example-*^ should be called.
I can't figure out how to get the string to be passed as a function / command name. What am I doing wrong?
So far I tried combinations of `',#, (intern), (eval), (function) but I have no idea what I should be doing.

One reason your code doesn't work is because you quoted the (concat ..) expression so it's never evaluated. And global-set-key expects a lambda or a symbol.
You can construct a symbol using intern, then provide the symbol to set-key:
(defun my-test () (interactive) (message "ok"))
(global-set-key "\C-c!" (intern (concat "my" "-" "test")))
Note that any function called via global-set-key and variants must be interactive.

Use lexical-let to define a closure, an anonymous function that references values from the environment in which it was defined:
(defun global-setter (arg1 arg2)
(lexical-let ((arg1 arg1) (arg2 arg2))
(global-set-key arg1 (lambda ()
(interactive)
(concat "example" arg1 arg2)))))
Emacs 24 natively supports lexical binding and closures, so lexical-let is no longer necessary:
(defun global-setter (arg1 arg2)
(global-set-key arg1 (lambda ()
(interactive)
(concat "example" arg1 arg2))))
For this to work, be sure to set lexical-binding to t in your .emacs and add this to the end of the file to ensure lexical-binding is used for byte-compilation:
;; Local Variables:
;; lexical-binding: t
;; End:

Related

Common lisp: calling a class method in a separate thread

I am trying to build a common lisp implementation of the channel construct of Golang for a personal project (also to learn lisp). So far I've implemented the channels as objects of a class, containing a queue, a lock and a condition variable to signal listening functions that a new message has been added to the queue. I'm using bordeaux threads to create threads, locks, condition variables and join the executions (from the lisp cookbook).
This is the channel class and the recive function:
(defclass channel ()
((messages :initform '()
:accessor messages
:documentation "Messages in the channel")
(lock :initform (bt:make-lock)
:accessor lock
:documentation
"Lock to push/pop messages in the channel")
(cv :initarg :cv
:initform (bt:make-condition-variable)
:accessor cv
:documentation
"Condtional variable to notify the channel of a new message")))
(defmethod recive-loop ((self channel))
(with-slots (lock cv messages) self
(let ((to-ret nil))
(loop
(bt:with-lock-held (lock)
(if (not (null messages))
(setf to-ret (car (pop messages)))
(bt:condition-wait cv lock))
(if to-ret (return to-ret)))))))
(defmethod recive ((self channel))
(with-slots (name thread) self
(let ((thread
(bt:make-thread #'(lambda() (recive-loop self))
:name name)))
(bt:join-thread thread))))
(defmacro gorun (f &rest args)
(flet ((fn () (apply f args)))
(bt:make-thread #'fn
:initial-bindings (list args)
:name "gorun worker")))
gorun should be the equivalent of go routine() for go (without the light threading). To test the setup I've built a printer function over a channel
(defvar printch (channel))
(defun printover (ch)
(let ((x (recive ch)))
(format t "Recived variable x: ~d~%" x)))
but when I run
(gorun printover printch)
The interpreter (using sbcl, but with clisp the same happens) gives back an error:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::RECIVE (1)>
when called with arguments
(PRINTCH).
[Condition of type SB-PCL::NO-APPLICABLE-METHOD-ERROR]
See also:
Common Lisp Hyperspec, 7.6.6 [:section]
Restarts:
0: [RETRY] Retry calling the generic function.
1: [ABORT] abort thread (#<THREAD "gorun worker" RUNNING {100293E9F3}>)
Backtrace:
0: ((:METHOD NO-APPLICABLE-METHOD (T)) #<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::RECIVE (1)> PRINTCH) [fast-method]
Locals:
SB-PCL::ARGS = (PRINTCH)
GENERIC-FUNCTION = #<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::RECIVE (1)>
1: (SB-PCL::CALL-NO-APPLICABLE-METHOD #<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::RECIVE (1)> (PRINTCH))
Locals:
ARGS = (PRINTCH)
GF = #<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::RECIVE (1)>
2: (PRINTOVER PRINTCH)
Locals:
CH = PRINTCH
3: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS))
[No Locals]
I'm confused, since the method to run over the channel printch should be the one I've defined.
Trying to call a class method inside of a new thread, but got no applicable method
A macros is supposed to return code to run in place of the original call. Your macro is creating the thread at expansion time.
If you're not using backtick in a macro definition, there's usually something wrong with it. You should figure out what the code would look like without the macro, then define a macro that returns code with that same structure in a backticked list, replacing the places that need to vary with the parameters, using comma to expand them.
(defmacro gorun (f &rest args)
`(bt:make-thread (function ,f)
:initial-bindings (list ,#args)
:name "gorun worker"))
In the above, you need to substitute the function name into a (function ...) expression, and the args list as the :initial-bindings argument.
In multi-threaded environments it is often the case that special variables are thread-local. The global binding is visible from all threads, but if you bind one locally its value will not automatically be transferred to a thread created in that context. It has to be done explicitly, and I wrote a pair of macros recently just for that.
The first one captures bindings into lexically-scoped variables; the other bind the original variables back to the values captured in a different context.
I am using an intermediate data structure in the code to store bindings:
(defstruct bindings data)
The first macro is with-captured-bindings:
(defmacro with-captured-bindings ((&rest symbols) as name &body body)
(assert (eq as :as))
(loop for s in (alexandria:flatten
(sublis
'((:stdio *standard-output* *error-output* *standard-input*)
(:path *default-pathname-defaults*))
symbols))
for g = (gensym)
collect (list g s) into capture
collect (list s g) into rebind
finally
(return
`(let ,capture
,#(subst (make-bindings :data rebind)
name
body)))))
The capture variable holds a list of bindings to initialize the lexically-scoped variables. The rebind variables is a list of bindings to set back special variables to their values in another thread.
I inject with subst an instance of the bindings struct in the code. It helps to have a dedicated data structure, but the crude search-and-replace approach means the symbols name will not be usable as a function, local macro, etc. in body. I don't think it is too much of a problem.
Also, I define aliases like :stdio and :path for commonly used variables.
The second macro is with-bindings:
(defmacro with-bindings (bindings &body body)
(check-type bindings bindings)
`(let ,(bindings-data bindings)
,#body))
This replaces the intermediate struct with the proper code. The final code does not have this struct anymore and can be processed as usual.
For example:
(defvar *my-var* "hello")
(with-captured-bindings (:stdio :path *my-var*) :as <bindings>
(sb-thread:make-thread
(lambda ()
(with-bindings <bindings>
(print *var*)))))
A first application of macroexpand gives:
(LET ((#:G3882 *STANDARD-OUTPUT*)
(#:G3883 *ERROR-OUTPUT*)
(#:G3884 *STANDARD-INPUT*)
(#:G3885 *DEFAULT-PATHNAME-DEFAULTS*)
(#:G3886 *MY-VAR*))
(SB-THREAD:MAKE-THREAD
(LAMBDA ()
(WITH-BINDINGS #S(BINDINGS
:DATA ((*STANDARD-OUTPUT* #:G3882)
(*ERROR-OUTPUT* #:G3883)
(*STANDARD-INPUT* #:G3884)
(*DEFAULT-PATHNAME-DEFAULTS* #:G3885)
(*MY-VAR* #:G3886)))
(PRINT *MY-VAR*)))))
Notice that there is #S(BINDINGS ...) object in the tree.
The full expansion is:
(LET ((#:G3887 *STANDARD-OUTPUT*)
(#:G3888 *ERROR-OUTPUT*)
(#:G3889 *STANDARD-INPUT*)
(#:G3890 *DEFAULT-PATHNAME-DEFAULTS*)
(#:G3891 *MY-VAR*))
(SB-THREAD:MAKE-THREAD
(LAMBDA ()
(LET ((*STANDARD-OUTPUT* #:G3887)
(*ERROR-OUTPUT* #:G3888)
(*STANDARD-INPUT* #:G3889)
(*DEFAULT-PATHNAME-DEFAULTS* #:G3890)
(*MY-VAR* #:G3891))
(PRINT *MY-VAR*)))))

Lisp scope issue with setq?

I'm a noob at lisp, have only been using it for two weeks or so...
I have some global variable declared with setq:
(setq myvar '(WHATEVER))
and a function that is supposed to modify whatever variable I tell it to:
(defun MYFUN (varname)
(setq varname '(POOP))
)
but when I make the call: (MYFUN 'myvar)
and check the value of myvar now it still is (WHATEVER) how do I make the changes that are made in MYFUN persist?
There is no such thing as "declaring a global variable with setq", there is only "set the value of a variable with setq" and if you're doing that in the top lexical environment, the results are amusingly under-defined.
If you look at what the variable varname contains, it may well be the list (poop).
Also, the "q" at the end of setq actually means "quoted" (that is, the setq special form will not evaluate the first (and third, and fifth...) argument, but will do so for the second (and fourth, and sixth...).
It was, historically, used as a convenience, where (set (quote var) value) was less convenient than (setq var value). However, (set var value) has exactly the same effect as (setf (symbol-value var) value) and you should use that.
You're setting the value of the local variable varname, not the global variable whose name it contains. To do what you want you need to use the symbol-value accessor to indirect through it to get the global value's variable.
(defun myfun (varname)
(setf (symbol-value varname) '(poop)))
EDIT: didn't notice this first:
You have local varname and global varname both in the scope of the function body. Local name shadows the global name. So, if you change the local name to var it should work the way you wrote (checked in SBCL 1.2.13). But consider the following stylistic corrections:
For global variables, please use ear-muffs * around the name, so it should be *myvar*. Global variables are special (there is a way to make them normal, but it is not necessarily a good idea). Special variables have dynamic scope, in contrast to lexical scope of normal variables.
The variable must be declared with defvar or defparameter. You can use setq for this but the compiler is going to complain that the variable is not defined. Also, with setq the variable is not going to be special.
For a variable *myvar* to appear special inside the body of the function, it either needs to be declared (with defvar or defparameter) before function definition, or it needs to be declared special in the body of the function with (declare (special *myvar*)) and then declared with defvar or defparameter.
Here is the code of possible combinations of declarations and respective outputs:
;; This is a model solution:
(defvar *myvar* 'a)
*MYVAR*
(defun foo (var)
(setq *myvar* var))
(foo 'b)
*myvar*
B
;; Not using DEFVAR or DEFPARAMETER
(setq myvar 'a)
A
(defun bar (var)
(setq myvar var))
;; The value of the global MYVAR is still changed
(bar 'b)
myvar
B
(defun show-myvar ()
myvar)
;; But MYVAR is not special
(let ((myvar 'z))
(show-myvar))
B
;; Also can assign value to undeclared variable
(defun bar2 (var)
(setq myvar-1 var))
BAR2
(setq myvar-1 'a)
A
;; And it works
(bar2 'b)
myvar-1
B
;; Finally: show special undeclared (yet) variable
(defun show-special ()
(declare (special *special-var*))
*special-var*)
(defvar *special-var* 'a)
*SPECIAL-VAR*
(let ((*special-var* 'z))
(show-special))
Z
;; The same but with SETQ: variable is still not special
(defun show-special-setq ()
(declare (special *special-var-setq*))
*special-var-setq*)
(setq *special-var-setq* 'a)
A
(let ((*special-var-setq* 'z))
(show-special-setq))
A

Invalid function in Emacs Lisp

I'm creating a function in Emacs Lisp that will read that whole buffer aloud if there is no active region. Otherwise, it reads the active region.
(defun speak-my-text () "Speaks text in buffer."
(interactive)
(if (equal mark-active t)
(
(kill-ring-save (point-min) (point-max))
(start-process-shell-command "speakbuffvar" nil
"bash -c \"killall espeak;xsel --clipboard|espeak -s 290\"")
)
(
(kill-ring-save (region-beginning) (region-end))
(start-process-shell-command "speakbuffvar" nil
"bash -c \"killall espeak;xsel --clipboard|espeak -s 290\"")
)))
(global-set-key (kbd "C-z") 'speak-my-text)
I'm having trouble with the first line of the else clause:
(kill-ring-save (region-beginning) (region-end))
When I define the function, bind it, and run, I get "Invalid function" and it points to that line. I'm running Linux Mint.
Use C-h f progn to evaluate multiple expressions sequentially.
You're currently attempting to call a function named (kill-ring-save (region-beginning) (region-end)) and pass it the argument (start-process-shell-command ...)
Naturally, Emacs is telling you that (kill-ring-save (region-beginning) (region-end)) is not the name of a function.
In addition to phils' answer:
mark-active is not reliable in this context, as it might be
non-nil also if a region has no extend.
Function region-active-p would be usable, however depends on an
active transient-mark-mode, which might be unrelated - in most
cases it's useful and sufficient BTW.
Here is a example how to check for an valid region greater then
zero and surpassing transient-mark-mode issue:
(defun ar-region-active-p ()
"Check for and existing region of some extend.
Don't mix up that question with transient-mark-mode "
(interactive)
(and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))))
Based on this, your command might be written slightly differently:
(defun my-command-on-region ()
"If a region of some extend exists, use on it.
Otherwise use whole buffer.
Doesn't require `transient-mark-mode' being active"
(interactive)
(let ((beg (or (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))(region-beginning))
(point-min)))
(end (or (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))(region-end))
(point-max))))
(DO-SOMETHING beg end)))

How can I use setf on a dynamic variable effectively through a function call?

I am using dynamic variables, let's call one of them *x* with a value of 10.
I want to change its value through a function call by passing the variable's name as the parameter:
(defun change-value (varname)
(setf varname 20))
then calling (change-value *x*). If I understand correctly, varname takes local scope and therefore the setf has no effect outside change-value. So, *x* remains as 10 afterwards.
My question is, is there a way to make *x* equal to 20 through a function call similar to the above? I tried adding (proclaim '(special varname)) and (declare (special varname)) and they don't seem to do anything.
Oh, and defining a macro does more or less what I want, but I doubt this is good practice:
(defmacro change-value-macro (varname)
`(setf ,varname 20))
(change-value-macro *x*)
Defining
(defparameter *x* 10)
(defun change-value (varname) ; the argument name is misleading!
(setf varname 20))
and calling (change-value *x*) does not buy you anything because change-value is a function and you just passed it 10 as the argument; it has no idea that *x* is involved. So, what the function does is modify the local binding of the variable varname, changing it from 10 to 20 and returning the latter.
You need to pass the symbol (variable name) itself:
(defun change-value (varname)
(setf (symbol-value varname) 20))
and call it as (change-value '*x*) (note the quote mark ' before *x*).
This seems to work:
(defparameter *x* 'initial)
(defun change-dyn (variable value)
(setf (symbol-value variable) value))
(change-dyn '*x* 'final)

Want to access lexically defined functions using EVAL in CLISP

Why won't this piece of code work?
(setf x '(foo bar (baz)))
(labels
((baz () (print "baz here")))
(baz) ;works
(eval (third x))) ;fails with the below message
*** - EVAL: undefined function BAZ
I'm using GNU CLISP.
In Common Lisp, eval evaluates its argument in a null lexical environment, so your lexically bound function baz can't be found.
While the Common Lisp standard doesn't provide a portable way to access the lexical environment and invoke eval with it, your implementation might have this functionality. For example, in CLISP:
cs-user> (setf x '(foo bar (baz)))
(foo bar (baz))
cs-user> (labels ((baz () (print "baz here")))
(eval-env (third x) (the-environment)))
"baz here"
"baz here"
cs-user>
See geocar's answer for other approaches.
Because common lisp doesn't have special functions.
Check the description of EVAL:
Evaluates form in the current dynamic environment and the null lexical environment.
Since the lexical environment is empty, your baz function (defined by labels) isn't accessible. You'd think you could fix this by putting baz in the dynamic environment (you might want something like (declare (special baz)) or (declare (special (function baz))) or something like this) but alas: there's no way to do this.
You could simulate it yourself by creating:
(defvar baz* nil)
(defun baz (&rest args) (apply baz* args))
You then need to dynamically set baz* instead of using labels:
(setf x '(foo bar (baz)))
(let ((baz* (lambda () (print "baz here"))))
(eval (third x)))
The reason why is just some hard bits about optimisation leaking into the spec. Basically, every function-call would need some stubbing unless the compiler could prove that the function would never get defined dynamically swizzleable. That's hard to do efficiently, and it's not something most CL programmers ever did, so the spec-writers simply forbade it.
As you can see, and as with most things in CL, you can easily get it yourself if you need it. However. Given that most CL programmers never do this, you may want to re-examine why you're trying to do things this way.

Resources