21

Here is my answer to the identical question, appropriately edited: The Bad foo is self-modifying code. This is extremely dangerous. While the variable lst disappears at the end of the let form, its initial value persists in the function object, and that is the value you are modifying. Remember that in Lisp a function is a first class object, which can be ...


15

It means that when there is more than one binding the variables are bound sequentially, so that each can depend on the values bound to those that are bound before it, i.e., those that come before it in the let* bindings. For let (no asterisk), none of the bindings can be assumed to occur before any of the others (the variables could, in principle, be bound ...


15

Couldn't you use (cl-)letf while referencing the original function yourself? Something like this: ;; Original function (defun my-fun (arg) (message "my-fun (%s)" arg)) ;; Standard call (my-fun "arg") ;; => my-fun (arg) ;; Temporary overriding (more or less like an around advice) (let ((orig-fun (symbol-function 'my-fun))) (letf (((symbol-function '...


8

Common Lisp has a special facility - multiple values, and Emacs Lisp compatibility library emulates them using lists. Thus you can do (defun test-fun () (let ((a 1) (b 2)) (cl-values a b))) (cl-multiple-value-bind (a b) (test-fun) ...) (load cl-lib and use the cl- prefix for all CL functionality in EL). NB: if you look at the SO answer linked ...


7

You are looking to create a local variable, which can be done with a let-binding. Here's an example: (defun myfun-create-file () "Doc-string." (interactive) (let ((stamp (format-time-string "%Y-%m-%d--%H-%M-%S"))) (find-file-other-frame (concat "C:/Users/me/notes/" stamp ".txt")) (insert (concat "FILE-ID: " stamp ".txt\n"))))


6

I think a reasonable way is to collect all the values into a list and then use a destructuring bind, e.g., pcase-let: (pcase-let ((`(,a ,b ,c) (if t (list 1 2 3) (list 4 5 6)))) (list a b c)) or cl-multiple-value-bind (a bit cleaner than the pcase version since it is specialised to lists, and only allows a single binding clause): (cl-...


6

Definitions This topic confuses me sometimes, so let's start with some definitions, namely those of let: let is a special form in ‘C source code’. (let VARLIST BODY...) Bind variables according to VARLIST then eval BODY. The value of the last form in BODY is returned. Each element of VARLIST is a symbol (which is bound to nil) or a list (SYMBOL VALUEFORM)...


6

Store the original function (obtained with symbol-function) in a local variable, and use funcall to call the function object stored in that variable. Cumbersome, but it mostly works. (defadvice TeX-master-file (around TeX-master-file-indirect-buffer activate compile) "Support indirect buffers." (let ((original-buffer-file-name (symbol-function 'buffer-...


5

Looks like a macro could do that: (defmacro mylet (defs fun body) (list 'let (append defs (funcall fun)) body)) ;; example uses (defun the-dyn-gen () '((a 3) (b 3))) (mylet ((x 1) (y 2)) the-dyn-gen (+ a b x y)) (mylet ((x 1)) the-dyn-gen (+ a b x)) (mylet nil the-dyn-gen (+ a b)) Disclaimer: while this seems to work, macros can be tricky. Note ...


4

You can let-bind the keymap variable (presumably tex-file-mode-map) to a new keymap: (let ((tex-file-mode-map (make-sparse-keymap))) ...) Its value before binding it is restored after the let. After binding it, and within the body of the let, assign whatever different bindings you want. Be aware, however, that, any other changes to the map (e.g. by a ...


4

You're tripping over dynamic binding (as opposed to lexical binding). Your current-buffer-name is unbound at the point that your (lambda) function is executed. The let expression only binds it during the function's definition -- there's no closure to capture that value for subsequent evaluation. One simple workaround is to use backquoting like so: `(...


4

Beside relying on the cl-lib compatibility package, the recommended way in Elisp for that is to use pcase: (defun test-fun (let ((a '(a b)) (b '(c d))) `(,a ,b))) (defun other-test-fun () (pcase-let ((`(,a ,b) (test-fun))) (message "a = %s; b = %s" a b))) Beside pcase-let, there's also pcase-dolist, pcase-lambda, and pcase itself.


4

Here's one way to do it: (let ((a 2)) (pcase 2 ((pred (equal a)) 7))) This snippet uses the fact that (rephrasing (describe-function 'pcase)) a predicate may have the form(FUN ARG1 .. ARGN) in which case it gets called with an N+1'th argument which is the value being matched.


3

An alternative to pcase with similar features would also suffice (let ((a 2)) (cond ((eq a 2) 7))) ;; => 7 This isn't a joke - everything that can be done with pcase can also be done with a combination of let and cond. And it think it should be - gratuitous branch-introducing macros aren't helping anyone to either code faster or maintain ...


3

The problem is in the let-binding of your defvar form. The let will return the value of its last form. Currently, the last form is define-key, which returns the function symbol which you bound to the keys. Instead, you want to return the map you created: (defvar test-mode-map (let ((map (make-keymap))) (define-key map (kbd "M-S-RET") 'insert-text) ...


3

[This was going to be a comment to @Drew's answer, but the code will not be rendered correctly.] I gave this a try and wrote a macro using unwind-protect. (defmacro with-keybinding (map key command &rest body) `(let* ((map ,map) (key ,key) (newcommand ,command) (prevbinding (lookup-key map key))) (unwind-protect ...


3

No, the attributes of a face are global. Using face-remapping-alist you can make them buffer local, which won't make you happy. In your case, I would recommend that you define a new face, say my-performed-replacements with your preferred background. When replacing text, you could remap all occurrences of query-replace with my-performed-replacements. It ...


3

From the docstring of memory-use-counts, emphasis mine: Return a list of counters that measure how much consing there has been. Each of these counters increments for a certain kind of object. The counters wrap around from the largest positive integer to zero. Garbage collection does not decrease them. So this is the expected output. I couldn't ...


3

It looks like you want to alias a function name within the scope of the my-run-command body, so I'd suggest something more like: (defun my-run-command (command) (cl-letf (((symbol-function 'my-append) #'append)) (apply command))) (my-run-command '(my-append (3 6 8) (4 5))) => (3 6 8 4 5)


3

let* is like a recursive let meaning: (let* ((var1 VAL1) (var2 VAL2)) ...) is like (let ((var1 VAL1)) (let ((var2 VAL2)) ...)) Thereby the usage of capital letters for VAL1 and VAL2 indicates that those can also be expressions. The recursive let-binding has consequences if VAL2 depends actually on var1. The effect is already described in ...


3

Your example is likely not representative of the actual code you're using, but a good solution might be to create the closure in the macro and return the closure, instead of returning code which may or may not turn into a closure depending on lexical-binding: (defmacro repro () (let* ((kmap-sym (gensym "kmap-"))) `(let ((,kmap-sym (make-sparse-keymap))...


2

There is no idiomatic way to do it, IMO. Do what you like. If you want to be sure to test the condition only once that you are currently retesting, then here is another possibility, where I've used function my-test instead of your vague "x" or "X" (which doesn't seem to actually be referenced in the code you show, which uses t instead): (let* ((test (my-...


2

There is an ugly workaround using eval with the optional argument LEXICAL set to t. (defmacro repro () (let ((kmap-sym (gensym "kmap-"))) `(eval '(let ((,kmap-sym (make-sparse-keymap))) (define-key ,kmap-sym "a" (lambda () (interactive) (message "kmap is %s" ,kmap-sym))) ,kmap-sym) t))) It is ugly since the ...


1

A quoted list is a constant thus should not be modified, if you modify a constant inside a function, the function will be self-modifying code, for example, ;; Return how many this function is called (defun counter () (cl-incf (car '(0)))) (counter) ;; => 1 (counter) ;; => 2 (counter) ;; => 3 The function returns a different value each time it ...


1

Not very sure if the result meets your expectation. (defun foo (keymap) `(lambda () (interactive) (message "kmap is %s" ',keymap))) (defmacro repro () (let ((kmap-sym (gensym "kmap-"))) `(let ((,kmap-sym (make-sparse-keymap))) (define-key ,kmap-sym "a" (foo ,kmap-sym)) ,kmap-sym))) (setq lexical-binding nil) ;; => nil (...


1

I would like something along the lines of (let* ((cpoint (point)) (sbt0 (while (nth 3 (syntax-ppss)) (search-backward "[" 1 t))) As Basil pointed out, you're looking for progn, e.g.: (let* ((cpoint (point)) (sbt0 (progn (while (nth 3 (syntax-ppss)) (search-backward "[" 1 t)) (point))) ...


1

I'm aware of letcheck for this, but would prefer to have that kind of linting integrated into one of the tools Flycheck is using, ideally the byte-compiler itself. While one may argue that an unbound variable in a let that suspiciously looks like one of the previous bindings could still be resolved from outer scope, I severely doubt this will ever ...


1

I'm with Dan, but I'm posting here so the question can be marked as answered. Another thing to understand about the code you posted is that it uses let*, which imposes an ordering on the variable assignments so that the value of bds assigned in the 2nd line of the let is available for use in the 3rd and 4th lines of the let*. In a normal (let ((..., the ...


1

Using backquotes like this is a bad idea: everything within the backquote loses access to lexically-scoped variables, plus it won't be compiled, macros will be expanded late/repeatedly, kittens will suffer, your karma will go down, and then some. Better do something like ;; -*- lexical-binding:t -*- (defvar my-dynbound-var) (defun example-dynamic-fn () "...


1

You have too many backticks in the expression. If you nest n backticks, then you need n commas before the expression you want to splice. highlight-stages package shows which parts in a expression are quoted (not evaluated), FYI.


Only top voted, non community-wiki answers of a minimum length are eligible