Passing a symbol to a macro in emacs - emacs

I am new to macros. I am trying to write a macro to generate some functions:
(defmacro test (name)
`(defun ,(intern (concat "fun-" (symbol-name name))) ()
...))
I want to pass a symbol to this macro like (test 'stuff), but emacs gives me this error:
Debugger entered--Lisp error: (wrong-type-argument symbolp (quote stuff))
Is that telling me (quote staff) is not the right argument to symbol-name ? How can I fix this ?

This all seems OK. The only thing is that you should call your macro with an unquoted symbol, like this:
(test stuff)
The reason for this is that, as noted in the Emacs Lisp Manual :
Macros [...] operate on the unevaluated expressions for the arguments, not on the argument values as functions do.
When you pass symbols to functions, you are used to quote them to prevent them being considered as a variable name and evaluated to the associated value. However, macro arguments are not evaluated during the macro expansion, but afterwards, when the expansion itself gets evaluated.

Related

Backquote expansion in Lisp

I'm a Lisp beginner and I'm struggling to understand why the following code gives me an error.
(dolist (elem '(mapcar
mapcon))
(when (fboundp `',elem) (print "hello")))
Thanks.
Edit:
A bit more context. I wrote the following in Elisp and I don't know how to fix it.
(dolist (ui-elem '(menu-bar-mode
tool-bar-mode
tooltip-mode
scroll-bar-mode
horizontal-scroll-bar-mode))
(when (fboundp `',ui-elem) (ui-elem -1)))
Note
In your question you mix common-lisp and elisp, but they are two different languages. The question however touches on concepts that are identical in both languages.
The need to quote symbols
The code you want to write checks if a symbol is bound to a function.
What you already know probably is that you can call fboundp on a symbol to determines this:
(fboundp 'menu-bar-mode)
=> t
When you evalute the above form, 'menu-bar-mode is the same as (quote menu-bar-mode), and is evaluated as the symbol object menu-bar-mode. This is the value that is given as an argument to fboundp.
In you example you want to iterate over a list of symbols, call fboundp on it and call the function if the symbol denotes a function. You can do this as follows:
(dolist (s '(menu-bar-mode and other symbols))
(when (fboundp s)
(funcall s -1)))
The list of symbols '(menu-bar-mode and other symbols) is quoted, which means that when dolist evaluates it, it sees a list of symbols. The value to which s is bound at each iteration of the loop is a symbol object, there is no need to quote them.
Quoting a symbol is something you have to do when writing them in your code so that they are not interpreted as variables. When you iterate over a list of symbols, you already manipulate symbols.
Note also that both Common Lisp and Emacs Lisp are "Lisp-2", meanings that you have to use (funcall ui-elem -1) instead of writing (ui-elem -1). When you write the latter form, that means calling the function literally named ui-elem because for function application, the first symbol in the list is not evaluated, it is taken literally.
Too many levels of quoting
The actual error I have when I execute your code is:
(wrong-type-argument symbolp 'mapcar)
It may look like 'mapcar denotes a symbol, because when you want the interpreter to evaluate some code as a symbol, you need to quote it. However, Lisp printers write objects in a way that they can be read back to "similar" objects. The error message that is printed if I expect a symbol to be a number is the following, where symbol foo is printed unquoted:
(+ 'foo 3)
;; error: (wrong-type-argument number-or-marker-p foo)
In your error message, the form that you are trying to use as a symbol is (quote mapcar). Recall that when you directly call fboundp:
(fboundp 'mapcar)
It is the same as-if you wrote:
(fboundp (quote mapcar))
First, (quote mapcar) is evaluated, as the symbol mapcar. Then, fboundp is applied to that value.
But when you write the following, while ui-elem is bound to symbol mapcar:
(fboundp `',ui-elem)
This is equivalent to:
(fboundp `(quote ,ui-elem))
The argument to fboundp is evaluated as (quote mapcar). You have one extra level of quoting. You could write instead:
(fboundp `,ui-elem)
But then, you don't need to use backquote/comma, you can directly write:
(fboundp ui-elem)

pass a list to macro in Common Lisp

I'm having a problem passing a list to macro, where the list will be used to generate function name. For example, the code below causes an error.
(defmacro gen (str-lst)
`(defun ,(intern (string-upcase (car str-lst))) () (print "foo")))
(gen '("foo" "bar"))
The resulting error was:
*** - DEFUN/DEFMACRO: QUOTE is a special operator and may not be redefined. The following restarts are available: ABORT :R1
Abort main loop
How should I modify my code, and what is wrong with my code?
The thing makes me even more confused is that the code below, about which answer exits here, works fine.
(defmacro easy-one (str-lst)
`(mapc #'(lambda (str) (print str)) ,str-lst))
(easy-one '("foo" "bar"))
Don't quote the list. Macros don't evaluate their arguments, so you don't need to quote them to prevent them from being evaluated, like you do for ordinary functions.
(gen ("foo" "bar"))
When you quote it, you're executing
(get (quote ("foo" "bar")))
The value of str-list is the list (quote ("foo" "bar")), so (car str-list) is the symbol QUOTE. As a result, the macro expands to
(defun quote () (print "foo"))
That's why you get an error complaining that you're trying to redefine the built-in QUOTE.
The difference in your second example is that you're just substituting the parameter into the expansion, you're not using its value in the expansion code. So it expands to
(mapc #'(lambda (str) (print str)) '("foo" "bar")))
Here the list will be used when the expansion runs, not while the macro is being expanded. It needs to be quoted there, to prevent it from being evaluated as a function call.
You should use macroexpand to see how your macros are being expanded when debugging.

Why not quoting lambda?

I was told that I shouldn't quote lambda in, say,
(global-set-key (quote [f3]) '(lambda () (interactive) (other-window -1) ))
I tried that indeed if I don't quote lambda, it works equally well
(global-set-key (quote [f3]) (lambda () (interactive) (other-window -1) ))
However, I don't understand why the latter works (and is also being preferred, and now that the latter works, why the former also works).
If the lambda expression is defined as an other function, we would have called
(global-set-key (quote [f3]) 'my-function)
to prevent my-function to be evaluated immediately. I understand the lambda expression as an anonymous version of my-function. So why shouldn't lambda be quoted?
Thanks!
Using C-h f lambda <RET>:
A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY)
is self-quoting; the result of evaluating the lambda expression
is the expression itself.
So, this answers the question, why you don't need to quote the lambda expression. As to why you shouldn't do it... I think, this has to do with byte compilation. A quoted lambda expression is simply plain data. The byte code compiler has no choice but to include the expression as a constant list literal into its output. An unquoted lambda expression, on the other hand, can be compiled to byte code, resulting in faster execution.
List literals of the form (lambda (...) ...) are special-cased in emacs lisp evaluator and can be used as functions. That's why it works, regardless of whether you quote the lambda expression or not.

lisp macro expand with partial eval

I have following code which confuse me now, I hope some can tell me the difference and how to fix this.
(defmacro tm(a)
`(concat ,(symbol-name a)))
(defun tf(a)
(list (quote concat) (symbol-name a)))
I just think they should be the same effect, but actually they seem not.
I try to following call:
CL-USER> (tf 'foo)
(CONCAT "FOO")
CL-USER> (tm 'foo)
value 'FOO is not of the expected type SYMBOL.
[Condition of type TYPE-ERROR]
So, what's the problem?
What i want is:
(tm 'foo) ==> (CONCAT "FOO")
The first problem is that 'foo is expanded by the reader to (quote foo), which is not a symbol, but a list. The macro tries to expand (tm (quote foo)). The list (quote foo) is passed as the parameter a to the macro expansion function, which tries to get its symbol-name. A list is not a valid argument for symbol-name. Therefore, your macro expansion fails.
The second problem is that while (tm foo) (note: no quote) does expand to (concat "FOO"), this form will then be executed by the REPL, so that this is also not the same as your tf function. This is not surprising, of course, because macros do different things than functions.
First, note that
`(concat ,(symbol-name a))
and
(list (quote concat) (symbol-name a))
do the exact same thing. They are equivalent pieces of code (backquote syntax isn't restricted to macro bodies!): Both construct a list whose first element is the symbol CONCAT and whose second element is the symbol name of whatever the variable A refers to.
Clearly, this only makes sense if A refers to a symbol, which, as Svante has pointed out, isn't the case in the macro call example.
You could, of course, extract the symbol from the list (QUOTE FOO), but that prevents you from calling the macro like this:
(let ((x 'foo))
(tm x))
which raises the question of why you would event want to force the user of the macro to explicitly quote the symbol where it needs to be a literal constant anyway.
Second, the way macros work is this: They take pieces of code (such as (QUOTE FOO)) as arguments and produce a new piece of code that, upon macroexpansion, (more or less) replaces the macro call in the source code. It is often useful to reuse macro arguments within the generated code by putting them where they are going to be evaluated later, such as in
(defmacro tm2 (a)
`(print (symbol-name ,a)))
Think about what this piece of code does and whether or not my let example above works now. That should get you on the right track.
Finally, a piece of advice: Avoid macros when a function will do. It will make life much easier for both the implementer and the user.

Can you create interactive functions in an Emacs Lisp macro?

I'm trying to write a macro in emacs lisp to create some ‘helper functions.’
Ultimately, my helper functions will be more useful than what I have here. I realize that there may be better/more intuitive ways to accomplish the same thing (please post) but my basic question is why won't this work/what am I doing wrong:
(defmacro deftext (functionname texttoinsert)
`(defun ,(make-symbol (concatenate 'string "text-" functionname)) ()
(interactive)
(insert-string ,texttoinsert)))
(deftext "swallow" "What is the flight speed velocity of a laden swallow?")
(deftext "ni" "What is the flight speed velocity of a laden swallow?")
If I take the output of the macroexpand and evaluate that, I get the interactive functions I was intending to get with the macro, but even though the macro runs and appears to evaluate, I can't call M-x text-ni or text-swallow.
This does what you want:
(defmacro deftext (functionname texttoinsert)
(let ((funsymbol (intern (concat "text-" functionname))))
`(defun ,funsymbol () (interactive) (insert-string ,texttoinsert))))
As has been pointed out, the solution is to use intern instead of make-symbol.
It's possible to create multiple independent symbols with the same name, but only one of them can be the canonical symbol for the given name -- i.e. the symbol you will obtain when you refer to it elsewhere.
intern returns the canonical symbol for the given name. It creates a new symbol only if no interned symbol by that name already exists. This means that it will only ever create one symbol for any given name1.
make-symbol, on the other hand, creates a new symbol every time it is called. These are uninterned symbols -- each one is a completely valid and functional symbol, but not the one which will be seen when you refer to a symbol by its name.
See: C-hig (elisp) Creating Symbols RET
Because defun returns the symbol it sets, you can observe what's going on by capturing the return value and using it as a function:
(defalias 'foo (deftext "ni" "What is the flight speed velocity of a laden swallow?"))
M-x text-ni ;; doesn't work
M-x foo ;; works
or similarly:
(call-interactively (deftext "shrubbery" "It is a good shrubbery. I like the laurels particularly."))
The tricky part in all this -- and the reason that evaluating the expanded form did what you wanted, and yet the macro didn't -- is to do with exactly how and when (or indeed if) the lisp reader translates the name of the function into a symbol.
If we write a function foo1:
(defun foo1 (texttoinsert) (insert-string texttoinsert))
The lisp reader reads that as text, and converts it into a lisp object. We can use read-from-string to do the same thing, and we can look at the printed representation of the resulting lisp object:
ELISP> (car (read-from-string "(defun foo1 (texttoinsert) (insert-string texttoinsert))"))
(defun foo1
(texttoinsert)
(insert-string texttoinsert))
Within that object, the function name is the canonical symbol with the name "foo1". Note, however, that the return value we see from read-from-string is only the printed representation of that object, and the canonical symbol is represented only by its name. The printed representation does not enable us to distinguish between interned and uninterned symbols, as all symbols are represented only by their name.
(Skipping ahead momentarily, this is the source of your issue when evaluating the printed expansion of your macro, as that printed form is passed through the lisp reader, and what was once an uninterned symbol becomes an interned symbol.)
If we then move on to macros:
(defmacro deffoo2 ()
`(defun foo2 (texttoinsert) (insert-string texttoinsert)))
ELISP> (car (read-from-string "(defmacro deffoo2 ()
`(defun foo2 (texttoinsert) (insert-string texttoinsert)))"))
(defmacro deffoo2 nil
`(defun foo2
(texttoinsert)
(insert-string texttoinsert)))
This time the reader has read the macro definition into a lisp object, and within that object is the canonical symbol foo2. We can verify this by inspecting the object directly:
ELISP> (eq 'foo2
(cadr (cadr (nth 3
(car (read-from-string "(defmacro deffoo2 ()
`(defun foo2 () (insert-string texttoinsert)))"))))))
t
So for this macro, it is already dealing with that canonical symbol foo2 before any macro call/expansion happens, because the lisp reader established that when reading the macro itself. Unlike our previous simple function definition (in which the function symbol was determined by the lisp reader as the function was defined), when a macro is called & expanded the lisp reader is not utilised. The macro expansion is performed using pre-existing lisp objects -- no reading is necessary.
In this example the function symbol is already present in the macro, and because it is the canonical symbol we could use (foo2) elsewhere in our code to call that function. (Or, had I made the definition interactive, use M-x foo2.)
Finally getting back to the original macro from the question, it's obvious that the lisp reader never encounters a function name symbol for the function it will define:
ELISP> (car (read-from-string "(defmacro deftext (functionname texttoinsert)
`(defun ,(make-symbol (concatenate 'string \"text-\" functionname)) ()
(interactive)
(insert-string ,texttoinsert)))"))
(defmacro deftext
(functionname texttoinsert)
`(defun ,(make-symbol
(concatenate 'string "text-" functionname))
nil
(interactive)
(insert-string ,texttoinsert)))
Instead this object produced by the lisp reader contains the expression ,(make-symbol (concatenate 'string "text-" functionname)); and that backquoted expression will be evaluated at expansion time to create a new uninterned symbol which will be a part of the object created by that expansion.
In our earlier examples the resulting object had a car of defun (interned), and a cadr of foo1 or foo2 (both also interned).
In this last example, the object has a car of defun (interned) but a cadr of an uninterned symbol (with the name resulting from the concatenate expression).
And finally, if you print that object, the printed representation of that uninterned function symbol will be the symbol name, and reading that printed representation back by evaluating it would cause the function cell for the canonical symbol to be defined instead.
1 In fact the unintern function can be used to unintern a symbol, after which calling intern for the same name would naturally create a new symbol; but that's not important for this discussion.
FWIW, if you use lexical-binding, you don't need to use a macro:
(defun deftext (functionname texttoinsert)
(defalias (intern (concat "text-" functionname))
(lambda ()
(interactive)
(insert-string texttoinsert))))
It's been years, but I think you're probably missing an fset to define the function; see the docs if you are wanting it a compile time too.