How can I substitute a symbol name into a function created in a macro? I think I am missing something obvious here. For example, I am trying to make a macro that defines some variables and functions similar to the following,
(cl-defmacro mac (pkg)
(let (
;; Define some variables
(sym (intern (concat pkg "-file")))
(sym-def "default-file.el")
(sym-doc (concat "A custom var from `" pkg "'."))
;; Define some functions
(symfn (intern (concat pkg "-fn")))
(symfn-doc (concat "A function for `" pkg "'.")))
`(list
(defcustom ,sym ,sym-def ,sym-doc
:group (quote ,(make-symbol pkg))
:type '(choice (const :tag "None" nil)
file))
(defun ,symfn ()
,symfn-doc
(interactive)
(fn ,sym)))))
The function returned makes a call out to another function (fn) with a signature like
(defun fn (var) (symbol-value var))
So, it is expecting a call like (fn 'some-var). And, I want to be able to use the macro like
(mac "pack")
And have the following work,
pack-file ; works: "default-file.el"
(pack-fn) ; error: not a symbol
I have tried things like (quote ,sym), symbol-name, and others... But can't seem to get it right.
You want the call to fn to be (fn ',sym) (which you mention you tried in the question, but I suspect got wrong somehow).
You probably also want the expansion of the macro to be (progn ...) instead of (list ...).
(This was originally a comment: I'm putting it here just so there's an answer.)
Related
I'm trying to create a macro (bar) that should be used like this:
(let ((my-var "foo"))
(bar ("some")
:buzz (lambda () (format t "~a~%" my-var))))
The macro should basically just FUNCALL the lambda with taking MY-VAR into account.
What I've come up with is this:
(defmacro bar ((thing) &body body)
`(funcall (coerce (getf (list ,#body) :buzz) 'function)))
This works, it prints "foo".
But I'd like to know if this is how this is done or if there is a better way of doing this.
Well, for a start if you don't need the extra, unused argument, then this is just funcall, since (lambda ...) denotes a function.
(let ((my-var "foo"))
(funcall (lambda () (format t "~a~%" my-var))))
So even if you didn't want to call this funcall you could write it as a function, not a macro: it's not doing any code transformation. But presumably you actually do need this extra argument, and you are intending to use it for some purpose in the expansion, so what you need then is a macro which takes keyword arguments and just expands into a suitable funcall form:
(defmacro bar ((thing) &key (buzz '(lambda ())))
(declare (ignore thing))
`(funcall ,buzz))
Update
This question is no longer feasible.
Turned out ivy-read doesn't return immediately as I expected. I used C-g to cancel completion which skips the restoring ivy-format-function part.
I'm writing an ivy extension with dynamic collection. I'd like to return a list of list of strings instead of a list of strings as candidates. The default value of ivy-format-function only supports list of strings so I decide to change it to my own function while calling ivy-read then change it back.
I defined the following macro and function:
(defun ivy-foo ()
(interactive)
(with--ivy-foo-format-function
(ivy-read "Foo: "
#'ivy-foo-function
:dynamic-collection t
:require-match t
:action #'ivy-foo--action
:unwind #'ivy-foo--unwind
:history 'ivy-foo-history
:caller 'ivy-foo)))
(defmacro with--ivy-foo-format-function (&rest body)
`(let ((original-function ivy-format-function))
(setq ivy-format-function (lambda (candidates) (ivy-foo--format-function candidates original-function)))
,#body
(setq ivy-format-function original-function)))
(defun ivy-foo--format-function (candidates original-format-function)
(funcall original-format-function
(mapcar
(lambda (cand)
(if (listp cand)
(car cand)
cand))
candidates)))
(defun ivy-foo-function (str)
(list (list "cand1" str) (list "cand2" str)))
with--ivy-foo-format-function doesn't set ivy-format-function to the original value. I got error "Symbol's value as a variable is void: original-function". What's wrong?
Update: ivy-format-function is a defvar. Its default value is #'ivy--format-function-default
I'm trying to write an ELisp macro to generate a multiple functions based on some common data. For example, when I want to compute the fn names I write something like (I'm ignoring hygiene for the moment, I'm passing a symbol literal into the macro so evaluation shouldn't matter):
(cl-defmacro def-fns (sym)
"SYM."
(let ((s1 (make-symbol (concat (symbol-name sym) "-1")))
(s2 (make-symbol (concat (symbol-name sym) "-2"))))
`(progn (defun ,s1 () (+ 1 2 3))
(defun ,s2 () "six"))))
which I expect to generate 2 fns when invoked, called foo-1 and foo-2.
I should then be able to invoke the macro and fns like so:
(def-fns foo)
(foo-1)
;; => 6
(foo-2)
;; -> "six
Even the macroexpansion of (def-fns foo) in Emacs suggests that this should be the case:
(progn
(defun foo-1 nil (+ 1 2 3))
(defun foo-2 nil "six"))
However, when I evaluate the def-fns definition and invoke it it does not generate those functions. Why is this the case? This technique works in Common Lisp and in Clojure (which have very similar macro systems), so why not in ELisp?
Your code would not work in CL either.
The problem is with make-symbol - it creates a new symbol, so that
(eq (make-symbol "A") (make-symbol "A"))
==> nil
This means that your macro creates the functions but binds them to symbols which you no longer have a handle on.
When you evaluate (foo-1), Emacs Lisp reader tries to find the function binding of the interned symbol foo-1, not the fresh uninterned symbol your macro created.
You need to use intern instead: it makes the symbol "generally available", so to speak:
(eq (intern "a") (intern "a))
==> t
So, the corrected code looks like this:
(defmacro def-fns (sym)
"SYM."
(let ((s1 (intern (concat (symbol-name sym) "-1")))
(s2 (intern (concat (symbol-name sym) "-2"))))
`(progn (defun ,s1 () (+ 1 2 3))
(defun ,s2 () "six"))))
(def-fns foo)
(foo-1)
==> 6
(foo-2)
==> "six"
Notes:
If you were using CL, the uninterned symbols would have been printed as #:foo-1 and the source of your problem would have been obvious to you.
It is exceedingly rare that you really need to use make-symbol. Usually, you want to use either intern or gensym.
I would like to initiate dynamically a hash table with defmethod or defun using one of the arguments to create the name. For instance:
(defun foo (arg)
(let ((NAME (read-from-string (format nil "\*~S\*" arg))))
(defparameter NAME (make-hash-table))))
Of course, foo create hash table with the symbol NAME, instead of the value of NAME in let. What can I do to get the value of NAME to create this hash table?
General Remarks
It is almost always wrong to create global variables in functions.
It is also almost always wrong to create new symbols using read-from-string instead of intern.
Use a Macro
What you probably want is
(defmacro def-ht (name)
(let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
(symbol-package name))))
`(defparameter ,var (make-hash-table))))
(def-ht foo)
Use a Function
You might be able to do it in a function too - by inspecting the macroexpansion of a defparameter form and placing the needed stuff in the function:
(defun make-ht-var (name)
(let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
(symbol-package name))))
(setf (symbol-value var) (make-hash-table))
(proclaim (list var 'special))))
(make-ht-var 'foo)
Note that the argument to the function is quoted, but the argument to the macro is not.
You need to use a macro instead of a function. DEFPARAMETER will bind value of MAKE-HASH-TABLE to the symbol NAME because it evaluates at macro-expansion time which occurs earlier than run-time, which is when the function FOO binds the lexical value of NAME.
Look up the CL evaluation model for a deeper understanding.
(defmacro foo (arg)
(let ((name (read-from-string (format nil "*~S*" arg))))
`(defparameter ,name (make-hash-table))))
(foo "my-hash")
=> <hash-table 0x121>
*my-hash*
=> <hash-table 0x121>
I'm trying to create a function on the fly that would return one constant value.
In JavaScript and other modern imperative languages I would use closures:
function id(a) {
return function() {return a;};
}
but Emacs lisp doesn't support those.
I can create mix of identity function and partial function application but it's not supported either.
So how do I do that?
Found another solution with lexical-let
(defun foo (n)
(lexical-let ((n n)) #'(lambda() n)))
(funcall (foo 10)) ;; => 10
Real (Not Fake) Closures in Emacs 24.
Although Emacs 24 has lexical scooping when the variable lexical-binding has value t, the defun special form doesn’t work properly in lexically bound contexts (at least not in Emacs 24.2.1.) This makes it difficult, but not impossible, to define real (not fake) closures. For example:
(let ((counter 0))
(defun counting ()
(setq counter (1+ counter))))
will not work as expected because the symbol counter in the defun will be bound to the global variable of that name, if there is one, and not the lexical variable define in the let. When the function counting is called, if the global variable doesn’t, exist then it will obviously fail. Hoever if there is such a global variable it be updated, which is probably not what was intended and could be a hard to trace bug since the function might appear to be working properly.
The byte compiler does give a warning if you use defun in this way and presumably the issue will be addressed in some future version of Emacs, but until then the following macro can be used:
(defmacro defun** (name args &rest body)
"Define NAME as a function in a lexically bound context.
Like normal `defun', except that it works correctly in lexically
bound contexts.
\(fn NAME ARGLIST [DOCSTRING] BODY...)"
(let ((bound-as-var (boundp `,name)))
(when (fboundp `,name)
(message "Redefining function/macro: %s" `,name))
(append
`(progn
(defvar ,name nil)
(fset (quote ,name) (lambda (,#args) ,#body)))
(if bound-as-var
'nil
`((makunbound `,name))))))
If you define counting as follows:
(let ((counter 0))
(defun** counting ()
(setq counter (1+ counter))))
it will work as expected and update the lexically bound variable count every time it is invoked, while returning the new value.
CAVEAT: The macro will not work properly if you try to defun** a function with the same name as one of the lexically bound variables. I.e if you do something like:
(let ((dont-do-this 10))
(defun** dont-do-this ()
.........
.........))
I can’t imagine anyone actually doing that but it was worth a mention.
Note: I have named the macro defun** so that it doesn’t clash with the macro defun* in the cl package, however it doesn’t depend in any way on that package.
Stupid idea: how about:
(defun foo (x)
`(lambda () ,x))
(funcall (foo 10)) ;; => 10
Emacs lisp only has dynamic scoping. There's a lexical-let macro that approximates lexical scoping through a rather terrible hack.
Emacs 24 has lexical binding.
http://www.emacswiki.org/emacs/LexicalBinding
;; -*- lexical-binding:t -*-
(defun create-counter ()
(let ((c 0))
(lambda ()
(setq c (+ c 1))
c)))
(setq counter (create-counter))
(funcall counter) ; => 1
(funcall counter) ; => 2
(funcall counter) ; => 3 ...
http://www.emacswiki.org/emacs/FakeClosures