Here's my macro, what it is supposed to do is to wrap a body in let with bindings from vars-alist
(defmacro with-vars-alist (vars-alist &rest body)
`(let (,#(mapcar (lambda (cell) (list (car cell) (cdr cell))) vars-alist))
,#body))
When I am looking at what it expands to using following code
(defvar my-vars-alist '((var1 . "var1")
(var2 . "var2")))
(macroexpand-1 (with-vars-alist my-vars-alist `(concat ,var1 ,var2)))
I get an error cons: Wrong type argument: sequencep, my-vars-alist
However checking it (sequencep my-vars-alist) return t.
The error is probably has some simple solution, but I am just unable to find it.
Remember that arguments to macros are un-evaluated, which means that when you pass my-vars-alist as an argument, it is passed verbatim as the symbol my-vars-alist.
Therefore during the macro expansion, vars-alist evaluates to the symbol my-vars-alist rather than the list ((var1 . "var1") (var2 . "var2")).
So the error isn't complaining that the variable my-vars-alist doesn't contain a sequence as its value, but rather that the symbol my-vars-alist is not itself a sequence (which is correct -- it's a symbol).
checking it (sequencep my-vars-alist) return t.
Which is also correct, as there my-vars-alist is evaluated as a variable to its value of ((var1 . "var1") (var2 . "var2"))
So you need to eval that argument. e.g.:
,#(mapcar (lambda (cell) (list (car cell) (cdr cell)))
(eval vars-alist))
As vars-alist is already being evaluated to the symbol my-vars-alist, this change means that we are passing that symbol my-vars-alist to eval, which evaluates it as a variable to obtain the list needed for mapcar.
You probably also wanted to quote the form you pass to macroexpand-1 (or use M-x pp-macroexpand-last-sexp).
I looks like what you're trying to do is let-bind the keys of an alist to their values, so you can use the keys as variables in the let body. There's a built in macro for this in recent Emacs:
(let-alist '((a . 1) (b . 2))
(message "a: %d, b: %d" .a .b))
Related
I have a struct spider:
(defstruct spider omegas values k)
And an instance spider:
(set '*spider* (make-spider
:omegas '()
:values (list *input*)
:k '(#'omegashift #'dec #'dupval '((0 . #'dec) (1 . #'inc) (2 . #'dec)))))
But when I run the expression: (listp (car (spider-k *spider*)) on Emacs and SBCL (and SLIME is involved but I'm not sure what it is.)
The REPL returns T. This is obviously confusing as (car (spider-k *spider*) correctly returns #'OMEGASHIFT and (listp (function OMEGASHIFT)) properly returns NIL.
Why is (listp (car (spider-k *spider*)) true? Shouldn't it be false?
#'omegashift is a reader-macro that expands to the list (function omegashift).
When you evaluate (function omegashift) you get a function, but you're not evaluating it because you quoted the list. So you're just getting the list that the reader-macro expands to.
You'd see the same thing if you did (listp (car '('foo))). 'foo expands to the list (quote foo). This evaluates to the symbol foo, but the quote before the list prevents evaluation.
To get functions instead of lists, you need to evaluate the function expressions. You can do this by calling the function list rather than quoting a list.
(setq *spider* (make-spider
:omegas '()
:values (list *input*)
:k (list #'omegashift #'dec #'dupval (list (cons 0 #'dec) (cons 1 #'inc) (cons 2 #'dec)))))
You can also use backquote to simplify this:
(setq *spider* (make-spider
:omegas '()
:values (list *input*)
:k `(,#'omegashift ,#'dec ,#'dupval '((0 . ,#'dec) (1 . ,#'inc) (2 . ,#'dec)))))
Inside a backquoted expression, you use comma to mark the sub-expressions that you want to evaluate.
BTW, you should use setq to assign variables, not set with a quoted symbol. They're equivalent for global variables, but you can't use set with a local variable.
Coming from a C++ background, I'm trying to figure out how arguments are passed into methods in Elisp. While I acknowledge that maybe the wording could be different, I'm wondering if it is closer to the C++ idea of passing by reference or passing by value? If I alter the parameter in the method itself, will it alter the parameter that was passed in in the function call?
All Lisps (Emacs Lisp, Common Lisp) pass parameters by value, always:
(defparameter x 42) ; defconst in Emacs Lisp
(defun test (x)
(setq x 10))
(test x)
==> 10
x
==> 42
Note, however, that some values are actually pointers (or, rather, objects with components), so a function can modify their content by side effects:
(defparameter x (list 1 2))
(defun test (x)
(setf (first x) 42
(second x) 24
x 17))
(test x)
==> 17
x
==> (42 24)
PS1. Cf. When to use ' (or quote) in Lisp? -- "quoted arguments" are evaluated too: the evaluation strips the quote.
PS2. Cf. add-to-list - it accepts a symbol (variable name) and modifies its value. This only works for global dynamic variables, not for lexical variables. Not a very good idea.
Actually, in Emacs Lisp, there is no such thing like passing a argument by value or by reference, not to mention pointer. But all arguments passed to function will be evaluated in advance except those have a ' prefix. Always remember When you set a variable, you always just create symbol with a value.[1]
So if you want to modify a variable's value in a function, all you need to do is modifying the value of that variable's symbol in that function.
Check my code bellow.
(defvar my-val 1)
(defun my-func-value (val)
(setq val 2))
(defun my-func-symbol (sym)
;; NOTE! using set instead of setq,
;; casue we want symbol "my-val" be evaluated from "sym" here
(set sym 2))
(my-func-value my-val) ; evaluate my-val before passed into function
(message "my-val: %s" my-val) ; my-val: 1
(my-func-symbol 'my-val) ; pass my-val symbol directly into function
(message "my-val: %s" my-val) ; my-val: 2
Note! If the variable is a lexically-bound variable[2], it's still true that you can modified the symbol's value but not the value in the lexical environment.
Here is the code:
(let ((my-lexical-var 1))
(my-func-symbol 'my-lexical-var)
;; evaluate from lexical environment
(message "my-lexical-var: %s" my-lexical-var) ; my-lexical-var: 1
;; evaluate from the symbol
(message "symbol my-lexical-var: %s" (symbol-value 'my-lexical-var))
; symbol my-lexical-var: 2
I have various functions and I want to call each function with the same value. For instance,
I have these functions:
(defun OP1 (arg) ( + 1 arg) )
(defun OP2 (arg) ( + 2 arg) )
(defun OP3 (arg) ( + 3 arg) )
And a list containing the name of each function:
(defconstant *OPERATORS* '(OP1 OP2 OP3))
So far, I'm trying:
(defun TEST (argument) (dolist (n *OPERATORS*) (n argument) ) )
I've tried using eval, mapcar, and apply, but these haven't worked.
This is just a simplified example; the program that I'm writing has eight functions that are needed to expand nodes in a search tree, but for the moment, this example should suffice.
Other answers have provided some idiomatic solutions with mapcar. One pointed out that you might want a list of functions (which *operators* isn't) instead of a list of symbols (which *operators* is), but it's OK in Common Lisp to funcall a symbol. It's probably more common to use some kind of mapping construction (e.g., mapcar) for this, but since you've provided code using dolist, I think it's worth looking at how you can do this iteratively, too. Let's cover the (probably more idiomatic) solution with mapping first, though.
Mapping
You have a fixed argument, argument, and you want to be able to take a function function and call it with that `argument. We can abstract this as a function:
(lambda (function)
(funcall function argument))
Now, we want to call this function with each of the operations that you've defined. This is simple to do with mapcar:
(defun test (argument)
(mapcar (lambda (function)
(funcall function argument))
*operators*))
Instead of operators, you could also write '(op1 op2 op3) or (list 'op1 'op2 'op3), which are lists of symbols, or (list #'op1 #'op2 #'op3) which is a list of functions. All of these work because funcall takes a function designator as its first argument, and a function designator is
an object that denotes a function and that is one of: a symbol (denoting the function named by that symbol in the global environment), or a function (denoting itself).
Iteratively
You can do this using dolist. The [documentation for actually shows that dolist has a few more tricks up its sleeve. The full syntax is from the documentation
dolist (var list-form [result-form]) declaration* {tag | statement}*
We don't need to worry about declarations here, and we won't be using any tags, but notice that optional result-form. You can specify a form to produce the value that dolist returns; you don't have to accept its default nil. The common idiom for collecting values into a list in an iterative loop is to push each value into a new list, and then return the reverse of that list. Since the new list doesn't share structure with anything else, we usually reverse it destructively using nreverse. Your loop would become
(defun test (argument)
(let ((results '()))
(dolist (op *operators* (nreverse results))
(push (funcall op argument) results))))
Stylistically, I don't like that let that just introduces a single value, and would probably use an &aux variable in the function (but this is a matter of taste, not correctness):
(defun test (argument &aux (results '()))
(dolist (op *operators* (nreverse results))
(push (funcall op argument) results)))
You could also conveniently use loop for this:
(defun test2 (argument)
(loop for op in *operators*
collect (funcall op argument)))
You can also do somewhat succinctly, but perhaps less readably, using do:
(defun test3a (argument)
(do ((results '() (list* (funcall (first operators) argument) results))
(operators *operators* (rest operators)))
((endp operators) (nreverse results))))
This says that on the first iteration, results and operators are initialized with '() and *operators*, respectively. The loop terminates when operators is the empty list, and whenever it terminates, the return value is (nreverse results). On successive iterations, results is a assigned new value, (list* (funcall (first operators) argument) results), which is just like pushing the next value onto results, and operators is updated to (rest operators).
FUNCALL works with symbols.
From the department of silly tricks.
(defconstant *operators* '(op1 op2 o3))
(defun test (&rest arg)
(setf (cdr arg) arg)
(mapcar #'funcall *operators* arg))
There's a library, which is almost mandatory in any anywhat complex project: Alexandria. It has many useful functions, and there's also something that would make your code prettier / less verbose and more conscious.
Say, you wanted to call a number of functions with the same value. Here's how you'd do it:
(ql:quickload "alexandria")
(use-package :alexandria)
(defun example-rcurry (value)
"Calls `listp', `string' and `numberp' with VALUE and returns
a list of results"
(let ((predicates '(listp stringp numberp)))
(mapcar (rcurry #'funcall value) predicates)))
(example-rcurry 42) ;; (NIL NIL T)
(example-rcurry "42") ;; (NIL T NIL)
(defun example-compose (value)
"Calls `complexp' with the result of calling `sqrt'
with the result of calling `parse-integer' on VALUE"
(let ((predicates '(complexp sqrt parse-integer)))
(funcall (apply #'compose predicates) value)))
(example-compose "0") ;; NIL
(example-compose "-1") ;; T
Functions rcurry and compose are from Alexandria package.
I'm trying to write a Lisp macro that writes a bunch of macros, but I'm having problems generating macro code that uses the splice operator (in build-bind) that expands inside expressions first.
(defmacro define-term-construct (name filter-p list-keywords)
(let* ((do-list-name (output-symbol "do-~a-list" name))
(with-name (output-symbol "with-~a" name))
(do-filter-name (output-symbol "do-~as" name)))
`(progn
(defmacro ,do-list-name
(ls (&key ,#(append list-keywords '(id operation))) &body body)
(with-gensyms (el)
`(loop-list (,el ,ls :id ,id :operation ,operation)
(let (XXX,#(build-bind ,,name ,el))
(when (,',filter-p ,el)
(,',with-name ,el
,#body)))))))))
After the first pass I want to get:
(define-term-construct some some-p (args name))
->
(PROGN
(DEFMACRO DO-SOME-LIST (LS (&KEY ARGS NAME ID OPERATION) &BODY BODY)
(WITH-GENSYMS (EL)
`(LOOP-LIST (,EL ,LS :ID ,ID :OPERATION ,OPERATION)
(LET (,#(BUILD-BIND ,SOME ,EL))
(WHEN (SOME-P ,EL)
(WITH-SOME ,EL
,#BODY)))))))
Any idea what quote/quasiquotes should I use to get the desired code?
The output that you say that you want want to get has unbalanced commas. ,# already balances the backquote, so you cannot have ,SOME and ,EL. That's two levels of unquoting/splicing inside only one level of backquoting.
I suspect you want:
`(WITH-GENSYMS (EL) ... (LET (,#(BUILD-BIND 'SOME EL)) ...))
The some symbol comes in as an argument to the original macro and has to end up as a quoted symbol when passed to the build-bind function. The EL is evaluated straight. It's just a local variable introduced by the WITH-GENSYMS binding construct, and it is not in backquote context anymore because it is inside the splice.
Transliterating that back to the the original outer macro's backquote: SOME becomes ,name:
,#(build-bind ',name el) ;; two commas out balance two backquotes in
The symbol is spliced in under the umbrella of a protecting quote which will make sure it is treated as a symbol and not a variable.
The el does not need to be spliced in; it's not variable material but a hard-coded feature of the template being generated. If you were to put ,el it would look for an el variable in the define-term-construct macro's scope, where no such thing exists.
I want to do a macro in common lisp which is supposed to take in one of its arguments a list made of slots and strings. Here is the prototype :
(defclass time-info ()
((name :initarg name)
(calls :initarg calls)
(second :initarg second)
(consing :initarg consing)
(gc-run-time :initarg gc-run-time)))
(defun print-table (output arg-list time-info-list) ())
The idea is to print a table based on the arg-list which defines its structure. Here is an example of a call to the function:
(print-table *trace-output*
'("|" name "||" calls "|" second "\")
my-time-info-list)
This print a table in ascII on the trace output. The problem, is that I don't know how to explicitely get the elements of the list to use them in the different parts of my macro.
I have no idea how to do this yet, but I'm sure it can be done. Maybe you can help me :)
I would base this on format. The idea is to build a format string
from your arg-list.
I define a helper function for that:
(defun make-format-string-and-args (arg-list)
(let ((symbols ()))
(values (apply #'concatenate 'string
(mapcar (lambda (arg)
(ctypecase arg
(string
(cl-ppcre:regex-replace-all "~" arg "~~"))
(symbol
(push arg symbols)
"~a")))
arg-list))
(nreverse symbols))))
Note that ~ must be doubled in format strings in order to escape them.
The printing macro itself then just produces a mapcar of format:
(defmacro print-table (stream arg-list time-info-list)
(let ((time-info (gensym)))
(multiple-value-bind (format-string arguments)
(make-format-string-and-args arg-list)
`(mapcar (lambda (,time-info)
(format ,stream ,format-string
,#(mapcar (lambda (arg)
(list arg time-info))
arguments)))
,time-info-list)))
You can then call it like this:
(print-table *trace-output*
("|" name "||" calls "|" second "\\")
my-time-info-list)
Please note the following errors in your code:
You need to escape \ in strings.
Second is already a function name exported from the common-lisp
package. You should not clobber that with a generic function.
You need to be more precise with your requirements. Macros and Functions are different things. Arrays and Lists are also different.
We need to iterate over the TIME-INFO-LIST. So that's the first DOLIST.
The table has a description for a line. Each item in the description is either a slot-name or a string. So we iterate over the description. That's the second DOLIST. A string is just printed. A symbol is a slot-name, where we retrieve the slot-value from the current time-info instance.
(defun print-table (stream line-format-description time-info-list)
(dolist (time-info time-info-list)
(terpri stream)
(dolist (slot-or-string line-format-description)
(princ (etypecase slot-or-string
(string slot-or-string)
(symbol (slot-value time-info slot-or-string)))
stream))))
Test:
> (print-table *standard-output*
'("|" name "||" calls "|" second "\\")
(list (make-instance 'time-info
:name "foo"
:calls 100
:second 10)
(make-instance 'time-info
:name "bar"
:calls 20
:second 20)))
|foo||100|10\
|bar||20|20\
First, you probably don't want the quote there, if you're using a macro (you do want it there if you're using a function, however). Second, do you want any padding between your separators and your values? Third, you're probably better off with a function, rather than a macro.
You also seem to be using "array" and "list" interchangeably. They're quite different things in Common Lisp. There are operations that work on generic sequences, but typically you would use one way of iterating over a list and another to iterate over an array.