Let's say you want to get the lambda list of every function in a package. On SBCL, using iterate you could do this
(use-package :iterate)
(defun lambda-lists (package)
(iter (for symbol in-package (find-package package))
(collect (sb-introspect:function-type symbol))))
To be more portable you might try something like this
(defun lambda-lists (package)
(iter (for symbol in-package (find-package package))
(collect (function-lambda-expression symbol))))
But this won't work since function-lambda-expression takes a function, not a symbol.
Something like (function symbol) won't work either since it makes a function called symbol, not a function called the value of symbol.
Is there a way to realize this with macro?
First you need to find out which symbol denotes a global function and not a macro or special form. See: FBOUNDP, MACRO-FUNCTION, SPECIAL-OPERATOR-P
Then you need to retrieve the function from the symbol: use SYMBOL-FUNCTION.
Related
I'm attempting to use a string saved in a variable to call a function like so:
(defn update-product-list [] "Test")
(defn handle-state-change [action]
((resolve (symbol action))))
(handle-state-change "update-product-list")
However, this gives me the following error: Assert failed: Argument to resolve must be a quoted symbol
I've also tried changing the above line to:
((resolve (quote (symbol action))))
But this still gives an error. I also tried changing it just to:
((resolve 'action))
But this gives a different error I don't quite understand: js/action is shadowed by a local. I don't want to override the function just call it. Not sure where I'm going wrong. I've looked at a few examples, but can't see to pin it down.
ClojureScript supports :advanced optimization, in which Google Closure Compiler will rename, inline, or eliminate (unused) functions in order to implement minification. In short, the name of the function you want to look up will, in general, simply no longer exist under :advanced.
Because of this, ClojureScript's resolve is a compile-time facility (a macro requiring a literal quoted symbol).
If you are using :simple or self-hosted ClojureScript, more options are available to you because the support needed persists into runtime. For example Planck has a planck.core/resolve that behave's like Clojure's resolve. A similar approach is possible in Lumo, and similar facilities can be fashioned if using :simple.
In general though, given :advanced, if you need to map strings to a set of functions, you need to somehow arrange to have a static mapping constructed at compile time to support this (the set of functions must be known a priori, at compile time).
If you have a namespace (the name of which is statically known at compile time) which defines functions that need to be dynamically called via strings, you could consider making use of ns-publics:
cljs.user=> (ns foo.core)
foo.core=> (defn square [x] (* x x))
#'foo.core/square
foo.core=> (in-ns 'cljs.user)
nil
cljs.user=> (when-some [fn-var ((ns-publics 'foo.core) (symbol "square"))]
(fn-var 3))
9
This will work under :advanced. The mapping constructed by ns-publics is static; built at compile-time. If you have multiple namespaces that need such treatment, you could merge several calls to ns-publics to build a larger map.
The advantage of this approach is that the code involved is pretty short and requires little maintenance. The disadvantage is that it dumps all of the public vars of the namespace (foo.core in this example) into your generated code (and the generated code for vars is somewhat verbose). Another disadvantage is that you need to statically know the namespace(s) involved at compile time.
If you need to further minimize generated code size, you could just build / maintain a simple static map from string to function value as in
(def fns {"square" foo.core/square})
and use it appropriately, keeping it up to date as your codebase evolves.
Another option would be to mark the functions that you need to access using ^:export meta, and then to call those functions using JavaScript interop. For example if you define the function this way
(defn ^:export square [x] (* x x))
then you can use strings / interop to lookup the function and call it at runtime. Here's an example:
((goog.object/getValueByKeys js/window #js ["foo" "core" "square"]) 3)
The use of ^:export and :advanced is covered here. If you know that you are using :simple or less, then you can simply use JavaScript interop to call the functions of interest, without needn't to use ^:export.
Note that there is no general solution that would let you look up a function by name at runtime under :advanced without somehow putting some aspect of that function into your code at compile time. (In fact, if a function is not referenced in a way that Google Closure Compiler can statically, see, the function implementation will be completely eliminated as dead code.) In the above, ns-publics grabs all the vars for a namespace at compile time, rolling your own lookup map sets up static code to refer to the function value, and using ^:export statically arranges to make the name of the function persist into runtime.
You need to use it like this:
((resolve 'inc) 5)) => 6
or, deconstructed a bit:
(let [the-fn (resolve 'inc)]
(the-fn 7))
=> 8
If you have the function name as a string, use the symbol function to convert from string => symbol (from clojuredocs.org):
user=> ((-> "first" symbol resolve) [1 2 3])
1
And, never forget the Clojure CheatSheet!
I had gone through a different tutorials and manuals, but still can't put a things together.
As I understand, when I need to add a new function to an event while an old functional still saved, I am add a hook by calling add-hook. From the manual entry on the add-hook:
FUNCTION is added (if necessary) at the beginning of the hook list
unless the optional argument APPEND is non-nil
So the hook is just a list of a functions. But how is this list looks like? Works? From my little research I found that every cons cell besides the car and cdr have also an invisible unmentioned slot for a function pointer(may be an index, it doesn't matter). So how can I create manually a list of a functions, and execute it? Probably with add-to-list function, but everything I tried just triggers an errors. Also in the manual mentioned:
You can set a hook variable with setq like any other Lisp variable,
Something is wrong here, because a pointer to a function don't get copied with setq. I.e.:
(defun myfunc1 () (message "hello"))
(setq onemorefunc 'myfunc1)
After I execute the (onemorefunc), debugger triggers, the setq just ignores a value of the unnamed element in which the pointer stored.
To call a function that's in a variable, you have to use funcall or apply:
(funcall onemorefunc)
(apply onemorefunc '())
When Emacs is processing a hook variable, it iterates through the list:
(do ((hooks blah-hook (cdr hooks)))
((null hooks))
(funcall (car hooks)))
In your example, your setq merely makes onemorefunc another name for myfunc1. A hook needs to be a list, and you need to add your hook function to that list using add-hook, which is a glorified version of push, not replace the list completely with your function using setq. The mention of setq has misled you, though it's clear to someone who's familiar with hooks that it is telling you something else correctly. It says you can set a hook variable -- not a hook itself -- using setq, and you can, but what it doesn't make clear is that what you have to set that hook variable to is another list (of zero or more functions) not a function. Thus, assuming my-mode-start-hook is empty to begin:
(add-hook 'my-mode-start-hook #'my-func)
is equivalent to:
(setq my-mode-start-hook (list #'my-func))
In practice, you should always do the former, never the latter unless and until you're really sure you know what you're doing.
I would like to create a nil function that takes any number of symbols and sets them all to nil.
(defun clean (as many args as given by user)
(setq each-arg nil)
)
(clean x y z)
How to do this 'cleanly'?
Since you're not quoting the arguments, it has to be a macro:
(defmacro clean (&rest symbols)
`(progn
,#(mapcar (lambda (sym) (list 'setq sym 'nil))
symbols)))
Similar idea as Dmitry, but generates slightly less code:
(defmacro clean (&rest variables)
`(setq ,#(loop for var in variables nconc (list var nil))))
(macroexpand '(clean a b c d))
;; (setq a nil b nil c nil d nil)
Regarding your other questions:
simple, but time consuming way to know is to move the point to the function that you don't know and C-h f or M-xdescribe-function this will put the function name in the prompt (if it is indeed an Emacs Lisp function) and show the description and, if availably the location in the source code.
I'll try to explain, but I'm no language reference :)
defmacro - is similar to function, but it doesn't evaluate arguments. Macros are executed when your code is read and compiled into the bytecode. Their primary goal is to generate other code.
lambda - is a macro that creates an anonymous function and returns it.
mapcar - is a high-order function that applies a function to all elements of the list in succession and collects the result into a list in the order it applied the function.
&rest - is a special keyword in the function's lambda-list (i.e. the definition of parameters) which means literally that the identifier following this symbol is a list of all arguments on the right of it).
,# is a special operator used in macros, inside back-quote macros. It instructs the reader that the expression following it must be evaluated, treated as list, and all of its conses must be appended to the form that is being currently parsed.
I am trying to determine whether a given argument within a macro is a function, something like
(defmacro call-special? [a b]
(if (ifn? a)
`(~a ~b)
`(-> ~b ~a)))
So that the following two calls would both generate "Hello World"
(call-special #(println % " World") "Hello")
(call-special (println " World") "Hello")
However, I can't figure out how to convert "a" into something that ifn? can understand. Any help is appreciated.
You might want to ask yourself why you want to define call-special? in this way. It doesn't seem particularly useful and doesn't even save you any typing - do you really need a macro to do this?
Having said that, if you are determined to make it work then one option would be to look inside a and see if it is a function definition:
(defmacro call-special? [a b]
(if (#{'fn 'fn*} (first a))
`(~a ~b)
`(-> ~b ~a)))
This works because #() function literals are expanded into a form as follows:
(macroexpand `#(println % " World"))
=> (fn* [p1__2609__2610__auto__]
(clojure.core/println p1__2609__2610__auto__ " World"))
I still think this solution is rather ugly and prone to failure once you start doing more complicated things (e.g. using nested macros to generate your functions)
First, a couple of points:
Macros are simply functions that receive as input [literals, symbols, or collections of literals and symbols], and output [literals, symbols, or collections of literals and symbols]. Arguments are never functions, so you could never directly check the function the symbol maps to.
(call-special #(println % " World") "Hello") contains reader macro code. Since reader macros are executed before regular macros, you should expand this before doing any more analysis. Do this by applying (read-string "(call-special #(println % \" World\") \"Hello\")") which becomes (call-special (fn* [p1__417#] (println p1__417# "world")) "Hello").
While generally speaking, it's not obvious when you would want to use something when you should probably use alternative methods, here's how I would approach it.
You'll need to call macroexpand-all on a. If the code eventually becomes a (fn*) form, then it is guaranteed to be a function. Then you can safely emit (~a ~b). If it macroexpands to eventually be a symbol, you can also emit (~a ~b). If the symbol wasn't a function, then an error would throw at runtime. Lastly, if it macroexpands into a list (a function call or special form call), like (println ...), then you can emit code that uses the thread macro ->.
You can also cover the cases such as when the form macroexpands into a data structure, but you haven't specified the desired behavior.
a in your macro is just a clojure list data structure (it is not a function yet). So basically you need to check whether the data structure a will result is a function or not when it is evaluated, which can be done like show below:
(defmacro call-special? [a b]
(if (or (= (first a) 'fn) (= (first a) 'fn*))
`(~a ~b)
`(-> ~b ~a)))
By checking whether the first element of the a is symbol fn* or fn
which is used to create functions.
This macro will only work for 2 cases: either you pass it a anonymous function or an expression.
Is it possible to write an interactive defun with code "r" that has an additional optional argument (so that it does things within the selected region, but with another argument)? I would like something like the following:
(defun my-function (start end &optional arg)
"Do something with selected region"
(interactive "r")
(if arg
(setq val arg)
(setq val 2))
(do things...))
Looking at the documentation it says
'r': Point and the mark, as two numeric
arguments, smallest first. This is the
only code letter that specifies two
successive arguments rather than one.
No I/O.
I'm not sure if the 'No I/O' and 'two successive arguments' means that it takes 2 and only 2 arguments (i.e., limited to the region's start and end point as args). Although it allows me to evaluate and run the defun with an additional argument, Emacs appears to be ignoring it.
Thank you.
To make interactive ask for multiple parameters, separate them with a newline character. For instance, if you want your third parameter be bound to the value of the prefix argument, define your function like this:
(defun my-function (start end &optional arg)
"Do something with selected region"
(interactive "r\np")
(if arg
(setq val arg)
(setq val 2))
(do things...))
M-x describe-function interactive gives you further information.
A function can be called in two ways:
Interactively: This is what happens when a user calls the command, e.g. when it has been bound to a key.
From lisp: When the function is called from another lisp function. e.g. (r 100 200 t).
In your case, you have to make sure that the arguments match the interactive specification, in this case it must accept two arguments. The third will not be used when called interactively (so then it will get the value nil).
NO I/O means that it will not prompt the user for input (like it does when it asks for a file name).
If you want your function to act differently depending in when the region is active, you could ask the function (use-region-p).