Creating a closure around a private function in elisp - emacs

In elisp I have the following
(setq lexical-binding t)
(fset 'boom (cl-flet*
((tickle ()
(message "hi"))
(pickle ()
(tickle)))
(lambda ()
(pickle))))
(boom)
When I run the boom function I get the error
Symbol's value as variable is void: --cl-pickle--
What's going on here?
My intent is I would like to wrap private/helper functions and variables in a closure so I can better organize my code than everything being global.

Don't (setq lexical-binding t). You don't want to execute a command that sets this variable. Instead you want to describe to Emacs that the code you write uses lexical binding, and for that you need to add:
-*- lexical-binding:t -*-
somewhere on the first line of the file.

Related

how to write elisp helper function for refactoring

I am pretty new to emacs and I am not sure I understand what lisp should actually behave.
Suppose I have two function
(add-hook 'python-mode-hook
(lambda ()
add-to-list (make-local-variable 'company-backends) 'company-jedi))
(add-hook 'js2-mode-hook
(lambda ()
add-to-list (make-local-variable 'company-backends) 'company-tern))
I wrote the following function
(defun auto-complete (mode-hook backend)
(add-hook mode-hook
(lambda ()
add-to-list (make-local-variable 'company-backends) backend)))
(auto-complete 'js2-mode-hook 'company-tern)
but it does not work. I looked online and I found it is because elisp does not have closure!
So, how should I refactor these two code block?
add-to-list is a function, so you need to use it with parentheses, as (add-to-list...). Or invoke it using funcall or apply.
Elisp has closures. Do one of the following:
With file-local-variable lexical-binding non-nil:
(defun auto-complete (mode-hook backend)
(add-hook mode-hook
(lambda ()
(add-to-list (make-local-variable 'company-backends) backend))))
With lexical binding you get a closure, which encapsulates an environment where variable backend is defined. Its value in that environment is the value it has when the closure is created, but the variable remains when the anonymous function is used - you can use it as a variable.
See the Elisp manual, node Using Lexical Binding.
Regardless of the value of lexical-binding:
(defun auto-complete (mode-hook backend)
(add-hook mode-hook
`(lambda ()
(add-to-list (make-local-variable 'company-backends) ',backend))))
In this case, there is no closure, and there is no variable backend in the function. Instead, that variable is replaced by its value at the time and in the context where the defun is evaluated. You can use this if you do not need to use the variable when the anonymous function is called, and all you need is its value (at the time of definition of that function).
If you use a closure then the anonymous function can be byte-compiled. If you use the variable-replacement technique then it cannot - in that case, you are not creating an anonymous function at the time of defun evaluation (or for byte-compilation). Instead, you are creating a list: (lambda...), and that list is later interpreted as a function.

Mode-local variables in Emacs

I would like to have a global keyboard shortcut that shows the value of a variable. However, the variable's value could change according to the current major mode in the current buffer.
I tried to add the following to my ~/.emacs:
(defun my-elisp-mode-setup ()
(defvar-local *current-mode-var* "elisp-mode")
)
(defun my-sh-mode-setup ()
(defvar-local *current-mode-var* "sh-mode")
)
(add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-setup)
(add-hook 'sh-mode-hook 'my-sh-mode-setup)
If I now start Emacs with emacs test.sh and then type M-x describe-variable *current-mode-var* in the test.sh buffer, I get
*current-mode-var*'s value is "elisp-mode"
Automatically becomes buffer-local when set.
Documentation:
Not documented as a variable.
while I expected to get *current-mode-var*'s value is "sh-mode"
The variables are evaled only at first declaration. All further declarations are skipped.
You need a setq instead.
If all you want to do is examine a variable to determine the major mode (which it seems is what you are doing), then just examine variable major-mode. That's what it's for.
And if you want a key/command to do that, then just create one:
(defun which-mode ()
"Echo the current major mode in the echo area."
(interactive)
(message "Major mode: %s" major-mode))
Or use variable mode-name if you prefer a human-friendly major-mode name.
I prefer official native package https://www.emacswiki.org/emacs/ModeLocal .
It is better configurable, because you do not require add-hook
For example
(require 'mode-local)
(setq-mode-local sh-mode *current-mode-var* "sh-mode")
(setq-mode-local emacs-lisp-mode *current-mode-var* "elisp-mode")
Then by just changing mode cause changing the value of *current-mode-var*
defvar-local is a macro calling defvar and make-variable-buffer-local under the hood.
defvar SYMBOL [VALUE [DOC-STRING]
... But if SYMBOL is not void, VALUE is not evaluated, and SYMBOL’s value is left unchanged...
You code should be:
(defvar-local *current-mode-var*)
(defun my-elisp-mode-setup ()
(setq *current-mode-var* "elisp-mode"))
(add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-setup)
(defun my-sh-mode-setup ()
(setq *current-mode-var* "sh-mode"))
(add-hook 'sh-mode-hook 'my-sh-mode-setup)

Programatically insert text into command that normally blocks event loop

I'd like to implement a command that types the first few characters into an existing command and lets me type the rest.
For example, a variant of icicle-execute-extended-command that starts with "icicle-" already entered.
I have tried:
keyboard macros
fail (even on simple things like M-x i c i c l e s) for no apparent reason.
functions
calling icicle-execute-extended-command block the command sequence
How would I go about doing this in a generalized manner?
Nice question.
Here's something generic you can try:
(defun no-mondays ()
(interactive)
(minibuffer-with-setup-hook
(lambda()
(insert "monday"))
(call-interactively 'query-replace)))
And here's a refactoring:
(defun with-initial-minibuffer (str fun)
`(lambda ()
(interactive)
(minibuffer-with-setup-hook
(lambda ()
(insert ,str))
(call-interactively ',fun))))
(defalias 'no-weekends
(with-initial-minibuffer
"\\(?:satur\\|sun\\)day"
'query-replace-regexp))
If you are calling completing-read yourself in your command definition, then just pass the text to insert as the INITIAL-INPUT argument. That's what it's for.
If you use icicle-define-command or icicle-define-file-command (so that your command will be a multi-command), then same thing: pass the INITIAL-INPUT arg.
If you use such a macro, be sure to put something like this in the file that defines the command, so the macro definition is available a byte-compilation time:
(eval-when-compile
(or (condition-case nil
(load-library "icicles-mac") ; Use load-library to ensure latest .elc.
(error nil))
(require 'icicles-mac)))

Emacs: the code in the body of a defun or defmacro cannot refer to surrounding lexical variables?

Update 2013 May: As of GNU Emacs 24.3.1, (let .. (defun..)) bytecompiles just fine without warning and the bytecompiled code works the same as not-compiled code. Just don't forget to add the file variable lexical-binding: t to the file to be bytecompiled. Workarounds at the end of this question is now not necessary.
Lexical Binding - Emacs Lisp Manual has this paragraph:
Note that functions like symbol-value, boundp, and set only retrieve or modify a variable's dynamic binding (i.e. the contents of its symbol's value cell). Also, the code in the body of a defun or defmacro cannot refer to surrounding lexical variables.
I am not sure if I am getting the meaning of the second sentence right. In the following code which should be run in lexical binding mode, the code in the body of a defun is successfully referring to the lexical binding value of the name n.
(let ((n 0))
(defun my-counter ()
(incf n)))
(my-counter) ;; 1
(my-counter) ;; 2
Is the sentence simply saying that (let .. (defun ..)) is a bad practice?
Workarounds:
;; -*- lexical-binding: t -*-
;; a way to define the counter function without byte-compile error or warning
(defvar my--counter-func
(let ((n 0))
(lambda ()
(setq n (1+ n)))))
(defun my-counter ()
(funcall my--counter-func))
;; another way to define the counter function, again without byte-compile error or warning
(fset 'my-another-counter
(let ((n 0))
(lambda ()
(setq n (1+ n)))))
And here's the code for testing the above code:
;; run:
;; emacs -q --load path-to-the-el-file-of-this-code.el
(load "path-to-file-defining-my-counter.elc") ;; loading the ELC file to test if byte-compiled code runs as expected.
(print (my-counter)) ;; 1
(print (my-counter)) ;; 2
(print (my-another-counter)) ;; 1
(print (my-another-counter)) ;; 2
The code does not byte-compile well at least in Emacs 24.1.1. I saved the following code in the foo.el file, which uses setq in place of incf in order to avoid any possible effects by the cl library:
;; -*- lexical-binding: t -*-
(let ((n 0))
(defun my-counter ()
(setq n (1+ n))))
When I tried to byte-compile it (M-x byte-compile-filefoo.el), I got the following warning messages:
foo.el:3:1:Warning: Function my-counter will ignore its context (n)
foo.el:3:1:Warning: Unused lexical variable `n'
foo.el:5:11:Warning: reference to free variable `n'
foo.el:5:17:Warning: assignment to free variable `n'
All of the messages are indicating that the code in the body of the defun construct cannot refer to the surrounding lexical variable n as the manual claims.
Actually, when I loaded the byte-compiled code (M-x load-filefoo.elc) and evaluted the (my-counter) form, I got the following erorr:
Debugger entered--Lisp error: (void-variable n)
...
Unfortunately, I'm not sure why the code appears to work when evaluated in the form of source code.
As I replied on gnu.emacs.help, you can use (defalias 'foo (lambda ...)) to work around that limitation.
And that limitation is lifted in Emacs's development code.
It's perfectly fine to refer to variables in lexical scope(*) from within a defun, just as you are doing above, and just as the "my-ticker" example on that manual page does as well.
Either I am missing something the line in the manual that says:
the code in the body of a defun or defmacro cannot refer to
surrounding lexical variables.
should say something more like:
code in the body of a defun can only access lexical variables if they are defined within the same lexical scope.
NOTE: There are comments in the other answers about problems byte-compiling this kind of code. Those should be fixed in the latest emacs. I've verified in v24.2.50.1 that this byte compiles and loads correctly.

How does the following statement is interpreted by emacs

https://stackoverflow.com/a/663636/391104
(defun my-c++-mode-hook ()
(setq c-basic-offset 4)
(c-set-offset 'substatement-open 0))
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
Based on my investigation, I just need to add the above code into my .emacs and then it works magically.
Q1> What does defun my-c++-mode-hook () mean? a function definition in lisp?
Q2> What is the usage of following line? where should I trigger it or it is run automatically by emacs
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
Thank you
Q1: Yes, this is a function definition (hence defun). The second symbol is the name, which has the suffix '-hook' to indicate to humans that it is intended to be used as a hook. It could be given (almost) any arbitrary name without changing its behaviour. The empty () indicates the function takes no arguments. Everything else is the body of the function.
Q2: Basically, this adds a pointer to the previous function to the list of functions that are called when ever c++-mode is started. Whenever you start a mode, the Emacs looks for the mode hook, running all the functions in it. Both the function definition and the add-hook line need to go in your .emacs, and they will be run automatically when you start emacs.
To wrap your head around elisp, the introduction is highly recommended. It ships with emacs, and can be accessed from the info system: C-h i, then look for Elisp Introduction.