Nested macros for defalias don't work, but macroexpand output works? - Emacs Elisp [duplicate] - elisp

This question already has an answer here:
Can't call functions defined in macro with names generated by make-symbol
(1 answer)
Closed 3 years ago.
I'm trying to implement user command aliases with a customizable prefix for my package. I wrote two nested macros to accomplish this. The trs-defalias-from-suffix macro returns the correct value as if an alias was created, but none exists when I search for it with M-x. However, when I manually execute the macroexpand output with C-x C-e, the code works. It creates an alias.
That shouldn't be possible, AFAIK. Also, there is probably a better way to accomplish my goal.
I would like to know how to make the macros work, and/or a better way to make the customizable-prefix aliases.
The goal is to take the original function
trs-refile
and make an alias with a different prefix, for example "foobar-"
foobar-refile
If this seems like a strange goal, it's because I want a short prefix, but need to change "trs-" to something longer to be accepted by MELPA.
#+begin_src elisp
(setq trs-alias-prefix "foobar") ; an example value, because I didn't include the defcustom code.
(defun trs-alias-oldname (suffix)
"Reconstruct original function name from SUFFIX."
(make-symbol (concat "trs-" suffix)))
(defun trs-alias-newname (suffix)
"Make new function name from SUFFIX."
(make-symbol (concat trs-alias-prefix "-" suffix)))
(defun trs-alias-name-list (suffix)
"Make a list of new and old function names from SUFFIX."
(list (trs-alias-newname suffix) (trs-alias-oldname suffix)))
(defmacro trs-defalias-from-names (newname oldname)
"Make a defalias with NEWNAME and OLDNAME."
`(defalias ',newname ',oldname))
(defmacro trs-defalias-from-suffix (suffix)
"Make a defalias from SUFFIX."
(let ((trs-alias-name-list (trs-alias-name-list suffix)))
`(trs-defalias-from-names ,(car trs-alias-name-list) ,(nth 1 trs-alias-name-list))))
(trs-defalias-from-suffix "refile")
(trs-defalias-from-suffix "refile-up")
(trs-defalias-from-suffix "delete-this-buffer-and-file")
(trs-defalias-from-suffix "store-link-fold-drawer")
(trs-defalias-from-suffix "dired-zinks")
(trs-defalias-from-suffix "duplicate-heading-to-other-window")
(trs-defalias-from-suffix "region-ends-n-newlines")
(macroexpand '(trs-defalias-from-suffix "refile")) ; this returns the same as below
(defalias (quote leo-refile) (quote trs-refile)) ; this works
#+end_src
These are similar questions, and might already contain the answer:
How to give a list as arguments to a macro in elisp?
elisp macro to write a function?
Before I dive deeper into learning macros, however, I'd appreciate knowing that I'm headed in the right direction.

make-symbol returns an uninterned symbol.
Use intern to get the canonical interned symbol.
The printed representation of the symbol is the same in either case (i.e. the symbol's name) which is why evaluating the printed representation of the macroexpand output gives a different result (because the lisp reader interns the symbol names).

Related

Add extra action (recenter) to `org-forward-element`?

In org-mode, strike M-} which invoke org-forward-element is very handy to jump around.
However, the matching line always stay at the bottom. So I have to manually execute (recenter).
How could add the action (recenter) to org-forward-element?
I tried a decorator solution, but does not work.
(defun add-recenter(func)
(lambda ()
(func)
(recenter)))
(setq org-element-forward (add-recenter org-element-forward))
This seems to work:
(advice-add 'org-forward-element :after (lambda () (recenter)))
I first tried (advice-add 'org-forward-element :after 'recenter), but that didn't work, because if the advice function being added (in this case recenter) is interactive, its interactive spec overrides that of the old function (org-forward-element), which causes an error since recenter generates one argument while org-forward-element takes zero arguments.
The reason your code doesn't work is that in Emacs Lisp variables and functions are in separate namespaces, just like Common Lisp and unlike Scheme. This is sometimes described as "Lisp-2", as opposed to "Lisp-1". See e.g. this article: http://ergoemacs.org/emacs/lisp1_vs_lisp2.html
Basically every symbol has both a "value cell" and a "function cell". setq changes the symbol's value cell, and calling a symbol, like (foo), accesses its function cell. The corresponding Emacs Lisp code would be something like:
(defun add-recenter(func)
(lambda ()
(funcall func)
(recenter)))
(fset 'org-element-forward (add-recenter (symbol-function 'org-element-forward)))
That is essentially what the advice-add call above does.

Get variable value with a string in scheme

How can we get variable value with a string in scheme language as we can achieve this in Common Lisp:
> (defvar s 3)
> S
> (symbol-value (intern "S"))
> 3
I am accessing a parameter of parent function from the closure.
EDIT: I have found this solution, but I can't use eval because it evaluates at top level. Searching for alternatives.
(eval (string->symbol "s"))
EDIT 2: I have found that Common lisp code also try to find symbol in global space. So this question is basically for both Lisps(Common Lisp, Scheme).
Don't do that!
Variables are for when you know the variable at compile time. In that case it is never a string. You can still reason about strings in compile time but your code also needs to have a relation with the name for it to be interesting. When you use eval or other forms that evaluate structure and compile/run data in runtime you are probably not doing it right (but not always. I've in my 20 year career used eval intentionally in production code twice)
If you want to store values you use a data structure. An assoc would mimic a dynamic environment. You can also use a hash with a level indicator if the size is harmless.
You can't do what you want to do and in fact it is a confused thing to want to do.
Here's why what you are trying to do is confused. Consider how a Lisp system for which it was possible to do what you wanted would work. In particular consider something like this:
(define (foo a name)
(let ([b 10])
(display (get-value name))
(* a b)))
Where get-value is meant to be how you get the binding of whatever something is.
So, if I call (foo 10 "b") it should print 10 and return 100.
But wait: b is a compile-time constant in this code. Any compiler worth its salt is going to immediately turn this into
(define (foo a name)
(display (get-value name))
(* a 10))
And now there is no binding of b.
So there are two options here: what you want to work works and it is impossible to ever write a reasonable compiler for Scheme, or what you want to work doesn't work, and it is.

How to determine if a variable exists in Chicken Scheme?

Is there a way in Chicken Scheme to determine at run-time if a variable is currently defined?
(let ((var 1))
(print (is-defined? var)) ; #t
(print (is-defined? var)) ; #f
EDIT: XY problem.
I'm writing a macro that generates code. This generated code must call the macro in mutual recursion - having the macro simply call itself won't work. When the macro is recursively called, I need it to behave differently than when it is called initially. I would use a nested function, but uh....it's a macro.
Rough example:
(defmacro m (nested)
(if nested
BACKQUOTE(print "is nested")
BACKQUOTE(m #t)
(yes, I know scheme doesn't use defmacro, but I'm coming from Common Lisp. Also I can't seem to put backquotes in here without it all going to hell.)
I don't want the INITIAL call of the macro to take an extra argument that only has meaning when called recursively. I want it to know by some other means.
Can I get the generated code to call a macro that is nested within the first macro and doesn't exist at the call site, maybe? For example, generating code that calls (,other-macro) instead of (macro)?
But that shouldn't work, because a macro isn't a first-class object like a function is...
When you write recursive macros I get the impression that you have an macro expansion (m a b ...) that turns into a (m-helper a (b ...)) that might turn into (let (a ...) (m b ...)). That is not directly recursive since you are turning code into code that just happens to contain a macro.
With destructuring-bind you really only need to keep track of two variables. One for car and one for cdr and with an implicit renaming macro the stuff not coming from the form is renamed and thus hygenic:
(define-syntax destructuring-bind
(ir-macro-transformer
(lambda (form inject compare?)
(define (parse-structure structure expression optional? body)
;;actual magic happens here. Returns list structure with a mix of parts from structure as well as introduced variables and globals
)
(match form
[(structure expression) . body ]
`(let ((tmp ,expression))
,(parse-structure structure 'tmp #f body))))))
To check if something from input is the same symbol you use the supplied compare? procedure. eg. (compare? expression '&optional).
There's no way to do that in general, because Scheme is lexically scoped. It doesn't make much sense to ask if a variable is defined if an referencing an undefined variable is an error.
For toplevel/global variables, you can use the symbol-utils egg but it is probably not going to work as you expect, considering that global variables inside modules are also rewritten to be something else.
Perhaps if you can say what you're really trying to do, I can help you with an alternate solution.

Racket macro to define functions given a repeated pattern

The problem is quite difficult to explain because I need to collect my thoughts, so bear with me. I've been able to reduce the problem to a minimal example for illustrative purposes. The example will not make any sense as to what this would be useful for, but I digress. Say I want to extend the racket language to write things that look like this:
(define-something
(['a] 'whatever)
(['b 'c] 'whatever2))
Between the square brackets is a sequence of one or more symbols, followed by a sequence of racket expressions (the whatever's, which are not important for the problem statement)
The example would match a macro that looks something like this:
(define-syntax (define-something stx)
(syntax-case stx ()
[(_ ([symb ...] body ...) ...)
#'()]))
Actually here we match 0 or more symbols, but we can assume there is always going to be at least one.
In the macro's body I want to generate function definitions using the concatenated symbols as the identifier. So for our silly example the macro would expand to something like:
(define (a) 'whatever)
(define (bc) 'whatever2)
I have found a similar question where the poster generates functions using a pre-defined list of strings, but I am not that fluent with macro's so I have not been able to translate the concepts to solve my problem. I thought perhaps I could try generating a similar list (by concatenating the symbols) and applying their tactic, but I've been getting way too confused with all the ellipses in my macro definition. I'm also a bit confused about their use of an ellipsis in with-syntax.
It’s possible to solve this with with-syntax and syntax-case, but the easiest way to do this is by using syntax-parse’s syntax classes. By defining a syntax class that parses a list of symbols and produces a single concatenated identifier, you can lift the symbol parsing out of the macro body:
(require (for-syntax syntax/parse
racket/string))
(begin-for-syntax
(define-syntax-class sym-list
#:attributes [concatenated-id]
(pattern (~and stx (sym:id ...))
#:attr concatenated-id
(let* ([syms (syntax->datum #'(sym ...))]
[strs (map symbol->string syms)]
[str (string-append* strs)]
[sym (string->symbol str)])
(datum->syntax #'stx sym #'stx #'stx)))))
Now you can define your macro pretty easily:
(define-syntax (define-something stx)
(syntax-parse stx
[(_ (syms:sym-list body ...) ...)
#'(begin
(define (syms.concatenated-id) body ...)
...)]))
Note that this uses unquoted symbols in the name clause, so it would work like this:
(define-something
([a] 'whatever)
([b c] 'whatever2))
The names can’t be expressions that evaluate to symbols because the information needs to be known at compile-time to be available to macro expansion. Since you mentioned in a comment that this is for an FRP-like system, your signal graph will need to be static, like Elm’s is for example. If you want the ability to construct a dynamic signal graph, you’ll need a more complex strategy than macros since that information will need to be resolved at runtime.

How do I get a list of functions defined in an emacs-lisp file

Is it possible to get a list of functions defined in an emacs-lisp file? I found this sort of related answer: How do I get a list of Emacs lisp non-interactive functions?, but it involves a map over all of the atoms defined, not just what is in a file.
If the file in question has already been loaded, then you can modify the code in the question you link to filter out the symbols defined in other files:
(let ((funclist ()))
(mapatoms
(lambda (x)
(when (and (fboundp x) ; does x name a function?
(let ((f (symbol-file x)))
(and f (string= (file-name-base f) "my-file.el"))))
(push x funclist))))
funclist)
If the file has not been loaded, you would have to scan it with scan-sexps and find defun forms.
You might, however, prefer to use etags or imenu instead of scanning the file yourself.
Maybe a faster way is to look for the file in load-history, which will then give you the list of variables and functions defined therein.
Not sure if your asking for a non interactive approach.
With M-x occur ENT (defun.* ENT you get a buffer with more or less all function-definitions found in (current-buffer).
The quick&dirty way: extract all defuns via regex. It works instantly on a buffer with 5000 lines.
(-map 'cadr (s-match-strings-all "defun \\(.*?\\) " (buffer-string)))
This returns a list of function names that are defined via defun in the current open buffer. buffer-string returns content of a current buffer in a string, -map and s-match-string-all are taken from dash and s third party libraries (their GitHub pages explain how to install them), cadr returns a 2nd element of a list.
-map is analogous to Emacs built-in mapcar, it applies a function to each element of a list and returns a new list, s-match-string-all returns all possible regex matches in a string, parentheses in a regex denote a group (read more how to form Emacs regular expressions from EmacsWiki).
If you run it in eval-expression (Alt+:), it will just throw it into echo area, but that's not what you need. So below are variations that work with custom buffer or file. with-current-buffer allows to temporarily switch a buffer, while some code does actions inside it, f-read is a file reading function form another third-party library f.
(defun list-defined-functions (buffer)
(with-current-buffer buffer
(-map 'cadr (s-match-strings-all "defun \\(.*?\\) "
(buffer-string)))))
(defun list-defined-functions-in-file (file)
(-map 'cadr (s-match-strings-all "defun \\(.*?\\) "
(f-read file))))
Read Emacs Lisp manual and try to come up with whatever is useful for you.

Resources