I have the following common lisp functions: (aggregate line1 line2) and (queuer data result).
queuer should push into result either the values line1 and line2 if they have the 1st field different, or the aggregate of those 2 lines if they have the 1st field equal.
I do not know why it doesn't change my result list.
Note: I am initializing the result list with a (push (pop data) result) to have the first element there. The 2 lists are 1-depth nested lists (("1" "text") ("2" "text") (...)).
(defun aggregate (line1 line2)
(progn
(list
(nth 0 line1)
(nth 1 line1)
(nth 2 line1)
(concatenate 'string (nth 3 line1) ", " (nth 3 line2))
(concatenate 'string (nth 4 line1) ", " (nth 4 line2)))))
(push (pop x) y)
(defun queuer (data result)
(loop do
(let ((line1 (pop data))
(line2 (pop result)))
(if (equal (first line1) (first line2))
(progn
(push (aggregate line1 line2) result)
(print "=="))
(progn
(push line2 result)
(push line1 result)
(print "<>"))))
while data))
Thank you for any insights.
If you write functions in Lisp it is preferable to think 'functionally'. A function takes values and returns values. A typical rule would be to avoid side effects. So your function should return a result value, not 'modify' a variable value.
Instead of:
(defparameter *result* '())
(defun foo (a)
(push a *result*))
use:
(defparameter *result* '())
(defun foo (a result)
(push a result)
result)
(setf *result* (foo a *result*))
Note also that aggregate does not need the progn.
Slightly advanced (don't do that):
If you have a global list:
(defparameter *foo* '())
You can't push onto it, as we have seen, like this:
(defun foo (l)
(push 1 l))
If you call foo the variable *foo* is unchanged. Reason: Lisp does not pass a variable reference, it passes the value of the variable.
But how can we pass a reference? Well, pass a reference: a cons cell would do it (or a structure, a vector, a CLOS object, ...):
CL-USER 38 > (defparameter *foo* (list '()))
*FOO*
CL-USER 39 > (defun foo (ref)
(push 1 (first ref)))
FOO
CL-USER 40 > (foo *foo*)
(1)
CL-USER 41 > (foo *foo*)
(1 1)
Now, if we look at *foo*, it is changed. But we haven't really changed the variable. We have changed the first entry of the list.
CL-USER 42 > *foo*
((1 1))
But, don't do it. Program in a functional style.
You cannot modify the contents of a variable with a function that only takes the variable's value.
Take the following simple example:
(defun futile-push (thing list)
(push thing list))
(let ((foo (list 1)))
(futile-push 2 foo))
What happens?
Foo is evaluated to the list it points to.
2 evaluates to 2.
These two arguments are passed to the function.
Inside the function invocation:
Thing is now bound to 2.
List is now bound to the list (1).
Note that the list does not know that it is also referenced by the variable
foo outside the function.
foo
|
v
---------
list -> | 1 |NIL|
---------
Push modifies the variable list in such a way that it is now bound to
the list (2 1).
Note that this does not affect foo outside. Foo still points to
the same thing as before.
foo
|
v
--------- ---------
list -> | 2 | ----> | 1 |NIL|
--------- ---------
Futile-push returns the return value of the push form, which happens
to be the new value of list.
That return value is never used or bound, so it vanishes.
foo
|
v
---------
| 1 |NIL|
---------
The most straightforward way to do what you want is to return the new
value and then set the variable outside:
(let ((foo (list 1)))
(setf foo (not-so-futile-push 2 foo)))
If you need to do that at more than one place, it might be worthwhile
to write a macro for that which expands to the setf form. Note that
push is itself a macro for exactly these reasons.
When you call push in queuer, this changes the value of the binding "result", not the cons cell that result is pointing to.
(push x list)
is essentially equivalent to:
(setq list (cons x list))
As long as your queuer function is a function, it couldn't really be any other way. If you call it with the argument "my-queue", then that argument (a symbol) is evaluated when you call the function and the result of the evaluation -- a cons cell -- is passed to the function. There is no way to modify that cons cell to indicate that another cons cell should be "prepended" to it -- cons cells don't keep track of the things that point to them.
There are (at least) three possible solutions:
Write your code so that queuer returns the new queue, instead of expecting the argument to be modified (or "mutated").
Wrap the queue inside a mutable layer of indirection. You could for instance hold the queue in the car or the cdr of a cons cell. You would then be able to mutate (car result) or (cdr result) in your queuer function, for instance with push.
Convert queuer to be a macro instead of a function. You can then write code to mutate its argument that will essentially be 'inserted' in your code wherever you use the queuer macro.
I would personally recommend the first solution. Where you would then, if you had your mutating queuer, want to write:
(queuer-mutating data my-queue)
You would instead write something like:
(setf my-queue (queuer-not-mutating data my-queue))
When you initialize data variable using (push (pop data) result), it moves items from data to result instead of copying:
CL-USER> (setq data '(("1" "text1") ("2" "text2") ("3" "text3")))
(("1" "text1") ("2" "text2") ("3" "text3"))
CL-USER> (setq result nil)
NIL
CL-USER> (push (pop data) result)
;Compiler warnings :
; In an anonymous lambda form: Undeclared free variable DATA (3 references)
(("1" "text1"))
CL-USER> (print data)
(("2" "text2") ("3" "text3"))
(("2" "text2") ("3" "text3"))
CL-USER> (print result)
(("1" "text1"))
(("1" "text1"))
What you might want to use instead is (copy-list list) function:
CL-USER> (setq copy2 (copy-list data))
(("2" "text2") ("3" "text3"))
Related
Prelude
In Raku there's a notion called infinite list AKA lazy list which is defined and used like:
my #inf = (1,2,3 ... Inf);
for #inf { say $_;
exit if $_ == 7 }
# => OUTPUT
1
2
3
4
5
6
7
I'd like to implement this sort of thing in Common Lisp, specifically an infinite list of consecutive integers like:
(defun inf (n)
("the implementation"))
such that
(inf 5)
=> (5 6 7 8 9 10 .... infinity)
;; hypothetical output just for the demo purposes. It won't be used in reality
Then I'll use it for lazy evaluation like this:
(defun try () ;; catch and dolist
(catch 'foo ;; are just for demo purposes
(dolist (n (inf 1) 'done)
(format t "~A~%" n)
(when (= n 7)
(throw 'foo x)))))
CL-USER> (try)
1
2
3
4
5
6
7
; Evaluation aborted.
How can I implement such an infinite list in CL in the most practical way?
A good pedagogical approach to this is to define things which are sometimes called 'streams'. The single best introduction to doing this that I know of is in Structure and Interpretation of Computer Programs. Streams are introduced in section 3.5, but don't just read that: read the book, seriously: it is a book everyone interested in programming should read.
SICP uses Scheme, and this sort of thing is more natural in Scheme. But it can be done in CL reasonably easily. What I've written below is rather 'Schemy' CL: in particular I just assume tail calls are optimised. That's not a safe assumption in CL, but it's good enough to see how you can build these concepts into a language which does not already have them, if your language is competent.
First of all we need a construct which supports lazy evaluation: we need to be able to 'delay' something to create a 'promise' which will be evaluated only when it needs to be. Well, what functions do is evaluate their body only when they are asked to, so we'll use them:
(defmacro delay (form)
(let ((stashn (make-symbol "STASH"))
(forcedn (make-symbol "FORCED")))
`(let ((,stashn nil)
(,forcedn nil))
(lambda ()
(if ,forcedn
,stashn
(setf ,forcedn t
,stashn ,form))))))
(defun force (thing)
(funcall thing))
delay is mildly fiddly, it wants to make sure that a promise is forced only once, and it also wants to make sure that the form being delayed doesn't get infected by the state it uses to do that. You can trace the expansion of delay to see what it makes:
(delay (print 1))
-> (let ((#:stash nil) (#:forced nil))
(lambda ()
(if #:forced #:stash (setf #:forced t #:stash (print 1)))))
This is fine.
So now, we'll invent streams: streams are like conses (they are conses!) but their cdrs are delayed:
(defmacro cons-stream (car cdr)
`(cons ,car (delay ,cdr)))
(defun stream-car (s)
(car s))
(defun stream-cdr (s)
(force (cdr s)))
OK, let's write a function to get the nth element of a stream:
(defun stream-nth (n s)
(cond ((null s)
nil)
((= n 0) (stream-car s))
(t
(stream-nth (1- n) (stream-cdr s)))))
And we can test this:
> (stream-nth 2
(cons-stream 0 (cons-stream 1 (cons-stream 2 nil))))
2
And now we can write a function to enumerate an interval in the naturals, which by default will be an half-infinite interval:
(defun stream-enumerate-interval (low &optional (high nil))
(if (and high (> low high))
nil
(cons-stream
low
(stream-enumerate-interval (1+ low) high))))
And now:
> (stream-nth 1000 (stream-enumerate-interval 0))
1000
And so on.
Well, we'd like some kind of macro which lets us traverse a stream: something like dolist, but for streams. Well we can do this by first writing a function which will call a function for each element in the stream (this is not the way I'd do this in production CL code, but it's fine here):
(defun call/stream-elements (f s)
;; Call f on the elements of s, returning NIL
(if (null s)
nil
(progn
(funcall f (stream-car s))
(call/stream-elements f (stream-cdr s)))))
And now
(defmacro do-stream ((e s &optional (r 'nil)) &body forms)
`(progn
(call/stream-elements (lambda (,e)
,#forms)
,s)
,r))
And now, for instance
(defun look-for (v s)
;; look for an element of S which is EQL to V
(do-stream (e s (values nil nil))
(when (eql e v)
(return-from look-for (values e t)))))
And we can then say
> (look-for 100 (stream-enumerate-interval 0))
100
t
Well, there is a lot more mechanism you need to make streams really useful: you need to be able to combine them, append them and so on. SICP has many of these functions, and they're generally easy to turn into CL, but too long here.
For practical purposes it would be wise to use existing libraries, but since the question is about how to implemented lazy lists, we will do it from scratch.
Closures
Lazy iteration is a matter of producing an object that can generate the new value of a lazy sequence each time it is asked to do so.
A simple approach for this is to return a closure, i.e. a function that closes over variables, which produces values while updating its state by side-effect.
If you evaluate:
(let ((a 0))
(lambda () (incf a)))
You obtain a function object that has a local state, namely here the variable named a.
This is a lexical binding to a location that is exclusive to this function, if you evaluate a second time the same expression, you'll obtain a different anonymous function that has its own local state.
When you call the closure, the value stored in a in incremented and its value is returned.
Let's bind this closure to a variable named counter, call it multiple times and store the successive results in a list:
(let ((counter (let ((a 0))
(lambda () (incf a)))))
(list (funcall counter)
(funcall counter)
(funcall counter)
(funcall counter)))
The resulting list is:
(1 2 3 4)
Simple iterator
In your case, you want to have an iterator that starts counting from 5 when writing:
(inf 5)
This can implemented as follows:
(defun inf (n)
(lambda ()
(shiftf n (1+ n))))
Here is there is no need to add a let, the lexical binding of an argument to n is done when calling the function.
We assign n to a different value within the body over time.
More precisely, SHIFTF assigns n to (1+ n), but returns the previous value of n.
For example:
(let ((it (inf 5)))
(list (funcall it)
(funcall it)
(funcall it)
(funcall it)))
Which gives:
(5 6 7 8)
Generic iterator
The standard dolist expects a proper list as an input, there is no way you can put another kind of data and expect it to work (or maybe in an implementation-specific way).
We need a similar macro to iterate over all the values in an arbitrary iterator.
We also need to specify when iteration stops.
There are multiple possibilities here, let's define a basic iteration protocol as follows:
we can call make-iterator on any object, along with arbitrary arguments, to obtain an iterator
we can call next on an iterator to obtain the next value.
More precisely, if there is a value, next returns the value and T as a secondary value; otherwise, next returns NIL.
Let's define two generic functions:
(defgeneric make-iterator (object &key)
(:documentation "create an iterator for OBJECT and arguments ARGS"))
(defgeneric next (iterator)
(:documentation "returns the next value and T as a secondary value, or NIL"))
Using generic functions allows the user to define custom iterators, as long as they respect the specified behaviour above.
Instead of using dolist, which only works with eager sequences, we define our own macro: for.
It hides calls to make-iterator and next from the user.
In other words, for takes an object and iterates over it.
We can skip iteration with (return v) since for is implemented with loop.
(defmacro for ((value object &rest args) &body body)
(let ((it (gensym)) (exists (gensym)))
`(let ((,it (make-iterator ,object ,#args)))
(loop
(multiple-value-bind (,value ,exists) (next ,it)
(unless ,exists
(return))
,#body)))))
We assume any function object can act as an iterator, so we specialize next for values f of class function, so that the function f gets called:
(defmethod next ((f function))
"A closure is an interator"
(funcall f))
Also, we can also specialize make-iterator to make closures their own iterators (I see no other good default behaviour to provide for closures):
(defmethod make-iterator ((function function) &key)
function)
Vector iterator
For example, we can built an iterator for vectors as follows. We specialize make-iterator for values (here named vec) of class vector.
The returned iterator is a closure, so we will be able to call next on it.
The method accepts a :start argument defaulting to zero:
(defmethod make-iterator ((vec vector) &key (start 0))
"Vector iterator"
(let ((index start))
(lambda ()
(when (array-in-bounds-p vec index)
(values (aref vec (shiftf index (1+ index))) t)))))
You can now write:
(for (v "abcdefg" :start 2)
(print v))
And this prints the following characters:
#\c
#\d
#\e
#\f
#\g
List iterator
Likewise, we can build a list iterator.
Here to demonstrate other kind of iterators, let's have a custom cursor type.
(defstruct list-cursor head)
The cursor is an object which keeps a reference to the current cons-cell in the list being visited, or NIL.
(defmethod make-iterator ((list list) &key)
"List iterator"
(make-list-cursor :head list))
And we define next as follows, specializeing on list-cursor:
(defmethod next ((cursor list-cursor))
(when (list-cursor-head cursor)
(values (pop (list-cursor-head cursor)) t)))
Ranges
Common Lisp also allows methods to be specialized with EQL specializers, which means the object we give to for might be a specific keyword, for example :range.
(defmethod make-iterator ((_ (eql :range)) &key (from 0) (to :infinity) (by 1))
(check-type from number)
(check-type to (or number (eql :infinity)))
(check-type by number)
(let ((counter from))
(case to
(:infinity
(lambda () (values (incf counter by) t)))
(t
(lambda ()
(when (< counter to)
(values (incf counter by) T)))))))
A possible call for make-iterator would be:
(make-iterator :range :from 0 :to 10 :by 2)
This also returns a closure.
Here, for example, you would iterate over a range as follows:
(for (v :range :from 0 :to 10 :by 2)
(print v))
The above expands as:
(let ((#:g1463 (make-iterator :range :from 0 :to 10 :by 2)))
(loop
(multiple-value-bind (v #:g1464)
(next #:g1463)
(unless #:g1464 (return))
(print v))))
Finally, if we add small modification to inf (adding secondary value):
(defun inf (n)
(lambda ()
(values (shiftf n (1+ n)) T)))
We can write:
(for (v (inf 5))
(print v)
(when (= v 7)
(return)))
Which prints:
5
6
7
I'll show it with a library:
How to create and consume an infinite list of integers with the GTWIWTG generators library
This library, called "Generators The Way I Want Them Generated", allows to do three things:
create generators (iterators)
combine them
consume them (once).
It is not unsimilar to the nearly-classic Series.
Install the lib with (ql:quickload "gtwiwtg"). I will work in its package: (in-package :gtwiwtg).
Create a generator for an infinite list of integers, start from 0:
GTWIWTG> (range)
#<RANGE-BACKED-GENERATOR! {10042B4D83}>
We can also specify its :from, :to, :by and :inclusive parameters.
Combine this generator with others: not needed here.
Iterate over it and stop:
GTWIWTG> (for x *
(print x)
(when (= x 7)
(return)))
0
1
2
3
4
5
6
7
T
This solution is very practical :)
I have the following setup in Common Lisp. my-object is a list of 5 binary trees.
(defun make-my-object ()
(loop for i from 0 to 5
for nde = (init-tree)
collect nde))
Each binary tree is a list of size 3 with a node, a left child and a right child
(defstruct node
(min 0)
(max 0)
(ctr 0))
(defun vals (tree)
(car tree))
(defun left-branch (tree)
(cadr tree))
(defun right-branch (tree)
(caddr tree))
(defun make-tree (vals left right)
(list vals left right))
(defun init-tree (&key (min 0) (max 1))
(let ((n (make-node :min min :max max)))
(make-tree n '() '())))
Now, I was trying to add an element to one of the binary trees manually, like this:
(defparameter my-object (make-my-object))
(print (left-branch (car my-object))) ;; returns NIL
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
(print (left-branch (car my-object))) ;; still returns NIL
The second call to print still returns NIL. Why is this? How can I add an element to the binary tree?
The first function is just:
(defun make-my-object ()
(loop repeat 5 collect (init-tree)))
Now you define a structure for node, but you use a list for the tree and my-object? Why aren't they structures?
Instead of car, cadr and caddr one would use first, second, third.
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
You set the local variable x to a new value. Why? After the let the local variable is also gone. Why aren't you setting the left branch instead? You would need to define a way to do so. Remember: Lisp functions return values, not memory locations you can later set. How can you change the contents in a list? Even better: use structures and change the slot value. The structure (or even CLOS classes) has following advantages over plain lists: objects carry a type, slots are named, accessors are created, a make function is created, a type predicate is created, ...
Anyway, I would define structures or CLOS classes for node, tree and object...
Most of the code in this question isn't essential to the real problem here. The real problem comes in with the misunderstanding of this code:
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
We can see the same kind of behavior without user-defined structures of any kind:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(let ((x (car cell)))
(setf x 3)
(print cell))) ; prints (1 . 2)
If you understand why both print statements produce (1 . 2), then you've got enough to understand why your own code isn't doing what you (previously) expected it to do.
There are two variables in play here: cell and x. There are three values that we're concerned with 1, 2, and the cons-cell produced by the call (cons 1 2). Variables in Lisp are often called bindings; the variable, or name, is bound to a value. The variable cell is bound to the the cons cell (1 . 2). When we go into the inner let, we evaluate (car cell) to produce the value 1, which is then bound to the variable x. Then, we assign a new value, 3, to the variable x. That doesn't modify the cons cell that contains the value that x was originally bound to. Indeed, the value that was originally bound to x was produced by (car cell), and once the call to (car cell) returned, the only value that mattered was 1.
If you have some experience in other programming languages, this is directly analogous to something like
int[] array = ...;
int x = array[2]; // read from the array; assign result to x
x = 42; // doesn't modify the array
If you want to modify a structure, you need to setf the appropriate part of the structure. E.g.:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(setf (car cell) 3)
(print cell)) ; prints (3 . 2)
I'm trying different binding models for macro lambda lists.
Edit: in fact the lambda list for my test macros is always (&rest ...). Which means that I'm 'destructuring' the argument list and not the lambda list. I try to get a solution that works for combining optional with key arguments or rest/body with key arguments - both combinations don't work in the Common Lisp standard implementation.
So I have different functions giving me a list of bindings having the same syntax as used by 'let'.
E.g:
(build-bindings ...) => ((first 1) middle (last "three"))
Now I thought to use a simple macro inside my test macros feeding such a list to 'let'.
This is trivial if I have a literal list:
(defmacro let-list (_list &rest _body)
`(let ,_list ,#_body))
(let-list ((a 236)) a) => 236
But that's the same as a plain 'let'.
What I'd like to have is the same thing with a generated list.
So e.g.
(let-list (build-bindings ...)
(format t "first: ~s~%" first)
last)
with (build-bindings ...), evaluated in the same lexical scope as the call (let-list ...), returning
((first 1) middle (last "three"))
the expansion of the macro should be
(let
((first 1) middle (last "three"))
(format t "first: ~s~%" first)
last)
and should print 1 and return "three".
Any idea how to accomplish that?
Edit (to make the question more general):
If I have a list of (symbol value) pairs, i.e. same syntax that let requires for it's list of bindings, e.g. ((one 1) (two 'two) (three "three")), is there any way to write a macro that creates lexical bindings of the symbols with the supplied values for it's &rest/&body parameter?
This is seems to be a possible solution which Joshua pointed me to:
(let ((list_ '((x 23) (y 6) z)))
(let
((symbols_(loop for item_ in list_
collect (if (listp item_) (car item_) item_)))
(values_ (loop for item_ in list_
collect (if (listp item_) (cadr item_) nil))))
(progv symbols_ values_
(format t "x ~s, y ~s, z ~s~%" x y z))))
evaluates to:
;Compiler warnings :
; In an anonymous lambda form: Undeclared free variable X
; In an anonymous lambda form: Undeclared free variable Y
; In an anonymous lambda form: Undeclared free variable Z
x 23, y 6, z NIL
I could also easily rearrange my build-bindings functions to return the two lists needed.
One problem is, that the compiler spits warnings if the variables have never been declared special.
And the other problem that, if the dynamically bound variables are also used in a surrounding lexical binding, they a shadowed by the lexical binding - again if they have never been declared special:
(let ((x 47) (y 11) (z 0))
(let ((list_ '((x 23) (y 6) z)))
(let
((symbols_(loop for item_ in list_
collect (if (listp item_) (car item_) item_)))
(values_ (loop for item_ in list_
collect (if (listp item_) (cadr item_) nil))))
(progv symbols_ values_
(format t "x ~s, y ~s, z ~s~%" x y z)))))
evaluates to:
x 47, y 11, z 0
A better way could be:
(let ((x 47) (y 11) (z 0))
(locally
(declare (special x y))
(let ((list_ '((x 23) (y 6) z)))
(let
((symbols_(loop for item_ in list_
collect (if (listp item_) (car item_) item_)))
(values_ (loop for item_ in list_
collect (if (listp item_) (cadr item_) nil))))
(progv symbols_ values_
(format t "x ~s, y ~s, z ~s~%" x y z))))))
evaluates to:
;Compiler warnings about unused lexical variables skipped
x 23, y 6, z NIL
I can't see at the moment whether there are other problems with the dynamic progv bindings.
But the whole enchilada of a progv wrapped in locally with all the symbols declared as special cries for a macro again - which is again not possible due to same reasons let-list doesn't work :(
The possiblilty would be a kind of macro-lambda-list destructuring-hook which I'm not aware of.
I have to look into the implementation of destructuring-bind since that macro does kind of what I'd like to do. Perhaps that will enlight me ;)
So a first (incorrect) attempt would look something like this:
(defun build-bindings ()
'((first 1) middle (last "three")))
(defmacro let-list (bindings &body body)
`(let ,bindings
,#body))
Then you could try doing something like:
(let-list (build-bindings)
(print first))
That won't work, of course, because the macro expansion leaves the form (build-bindings) in the resulting let, in a position where it won't be evaluated:
CL-USER> (pprint (macroexpand-1 '(let-list (build-bindings)
(print first))))
(LET (BUILD-BINDINGS)
(PRINT FIRST))
Evaluation during Macroexpansion time
The issue is that you want the result of build-bindings at macroexpansion time, and that's before the code as a whole is run. Now, in this example, build-bindings can be run at macroexpansion time, because it's not doing anything with any arguments (remember I asked in a comment what the arguments are?). That means that you could actually eval it in the macroexpansion:
(defmacro let-list (bindings &body body)
`(let ,(eval bindings)
,#body))
CL-USER> (pprint (macroexpand-1 '(let-list (build-bindings)
(print first))))
(LET ((FIRST 1) MIDDLE (LAST "three"))
(PRINT FIRST))
Now that will work, insofar as it will bind first, middle, and last to 1, nil, and "three", respectively. However, if build-bindings actually needed some arguments that weren't available at macroexpansion time, you'd be out of luck. First, it can take arguments that are available at macroexpansion time (e.g., constants):
(defun build-bindings (a b &rest cs)
`((first ',a) (middle ',b) (last ',cs)))
CL-USER> (pprint (macroexpand-1 '(let-list (build-bindings 1 2 3 4 5)
(print first))))
(LET ((FIRST '1) (MIDDLE '2) (LAST '(3 4 5)))
(PRINT FIRST))
You could also have some of the variables appear in there:
(defun build-bindings (x ex y why)
`((,x ,ex) (,y ,why)))
CL-USER> (pprint (macroexpand-1 '(let-list (build-bindings 'a 'ay 'b 'bee)
(print first))))
(LET ((A AY) (B BEE))
(PRINT FIRST))
What you can't do, though, is have the variable names be determined from values that don't exist until runtime. E.g., you can't do something like:
(let ((var1 'a)
(var2 'b))
(let-list (build-bindings var1 'ay var2 'bee)
(print first))
because (let-list (build-bindings …) …) is macroexpanded before any of this code is actually executed. That means that you'd be trying to evaluate (build-bindings var1 'ay var2 'bee) when var1 and var2 aren't bound to any values.
Common Lisp does all its macroexpansion first, and then evaluates code. That means that values that aren't available until runtime are not available at macroexpansion time.
Compilation (and Macroexpansion) at Runtime
Now, even though I said that Common Lisp does all its macroexpansion first, and then evaluates code, the code above actually uses eval at macroexpansion to get some extra evaluation earlier. We can do things in the other direction too; we can use compile at runtime. That means that we can generate a lambda function and compile it based on code (e.g., variable names) provided at runtime. We can actually do this without using a macro:
(defun %dynamic-lambda (bindings body)
(flet ((to-list (x) (if (listp x) x (list x))))
(let* ((bindings (mapcar #'to-list bindings))
(vars (mapcar #'first bindings))
(vals (mapcar #'second bindings)))
(apply (compile nil `(lambda ,vars ,#body)) vals))))
CL-USER> (%dynamic-lambda '((first 1) middle (last "three"))
'((list first middle last)))
;=> (1 NIL "three")
This compiles a lambda expression that is created at runtime from a body and a list of bindings. It's not hard to write a macro that takes some fo the quoting hassle out of the picture:
(defmacro let-list (bindings &body body)
`(%dynamic-lambda ,bindings ',body))
CL-USER> (let-list '((first 1) middle (last "three"))
(list first middle last))
;=> (1 NIL "three")
CL-USER> (macroexpand-1 '(let-list (build-bindings)
(list first middle last)))
;=> (%DYNAMIC-LAMBDA (BUILD-BINDINGS) '((LIST FIRST MIDDLE LAST)))
CL-USER> (flet ((build-bindings ()
'((first 1) middle (last "three"))))
(let-list (build-bindings)
(list first middle last)))
;=> (1 NIL "three")
This gives you genuine lexical variables from a binding list created at runtime. Of course, because the compilation is happening at runtime, you lose access to the lexical environment. That means that the body that you're compiling into a function cannot access the "surrounding" lexical scope. E.g.:
CL-USER> (let ((x 3))
(let-list '((y 4))
(list x y)))
; Evaluation aborted on #<UNBOUND-VARIABLE X {1005B6C2B3}>.
Using PROGV and special variables
If you don't need lexical variables, but can use special (i.e., dynamically scoped) variables instead, you can establish bindings at runtime using progv. That would look something like:
(progv '(a b c) '(1 2 3)
(list c b a))
;;=> (3 2 1)
You'll probably get some warnings with that if run it, because when the form is compiled, there's no way to know that a, b, and c are supposed to be special variables. You can use locally to add some special declarations, though:
(progv '(a b c) '(1 2 3)
(locally
(declare (special a b c))
(list c b a)))
;;=> (3 2 1)
Of course, if you're doing this, then you have to know the variables in advance which is exactly what you were trying to avoid in the first place. However, if you're willing to know the names of the variables in advance (and your comments seem like you might be okay with that), then you can actually use lexical variables.
Lexical variables with values computed at run time
If you're willing to state what the variables will be, but still want to compute their values dynamically at run time, you can do that relatively easily. First, lets write the direct version (with no macro):
;; Declare three lexical variables, a, b, and c.
(let (a b c)
;; Iterate through a list of bindings (as for LET)
;; and based on the name in the binding, assign the
;; corresponding value to the lexical variable that
;; is identified by the same symbol in the source:
(dolist (binding '((c 3) (a 1) b))
(destructuring-bind (var &optional value)
(if (listp binding) binding (list binding))
(ecase var
(a (setf a value))
(b (setf b value))
(c (setf c value)))))
;; Do something with the lexical variables:
(list a b c))
;;=> (1 NIL 3)
Now, it's not too hard to write a macrofied version of this. This version isn't perfect, (e.g., there could be hygiene issues with names, and declarations in the body won't work (because the body is being spliced in after some stuff). It's a start, though:
(defmacro computed-let (variables bindings &body body)
(let ((assign (gensym (string '#:assign-))))
`(let ,variables
(flet ((,assign (binding)
(destructuring-bind (variable &optional value)
(if (listp binding) binding (list binding))
(ecase variable
,#(mapcar (lambda (variable)
`(,variable (setf ,variable value)))
variables)))))
(map nil #',assign ,bindings))
,#body)))
(computed-let (a b c) '((a 1) b (c 3))
(list a b c))
;;=> (1 NIL 3)
One way of making this cleaner would be to avoid the assignment altogether, and the computed values to provide the values for the binding directly:
(defmacro computed-let (variables bindings &body body)
(let ((values (gensym (string '#:values-)))
(variable (gensym (string '#:variable-))))
`(apply #'(lambda ,variables ,#body)
(let ((,values (mapcar #'to-list ,bindings)))
(mapcar (lambda (,variable)
(second (find ,variable ,values :key 'first)))
',variables)))))
This version creates a lambda function where the arguments are the specified variables and the body is the provided body (so the declarations in the body are in an appropriate place), and then applies it to a list of values extracted from the result of the computed bindings.
Using LAMBDA or DESTRUCTURING-BIND
since I'm doing some "destructuring" of the arguments (in a bit a different way), I know which arguments must be present or have which
default values in case of missing optional and key arguments. So in
the first step I get a list of values and a flag whether an optional
or key argument was present or defaulted. In the second step I would
like to bind those values and/or present/default flag to local
variables to do some work with them
This is actually starting to sound like you can do what you need to by using a lambda function or destructuring-bind with keyword arguments. First, note that you can use any symbol as a keyword argument indicator. E.g.:
(apply (lambda (&key
((b bee) 'default-bee b?)
((c see) 'default-see c?))
(list bee b? see c?))
'(b 42))
;;=> (42 T DEFAULT-SEE NIL)
(destructuring-bind (&key ((b bee) 'default-bee b?)
((c see) 'default-see c?))
'(b 42)
(list bee b? see c?))
;;=> (42 T DEFAULT-SEE NIL)
So, if you just make your function return bindings as a list of keyword arguments, then in the destructuring or function application you can automatically bind corresponding variables, assign default values, and check whether non-default values were provided.
Acting a bit indirectly:
a solution that works for combining optional with key arguments or
rest/body with key arguments
Have you considered the not-entirely-uncommon paradigm of using a sub-list for the keywords?
e.g.
(defmacro something (&key (first 1) second) &body body) ... )
or, a practical use from Alexandria:
(defmacro with-output-to-file ((stream-name file-name
&rest args
&key (direction nil direction-p)
&allow-other-keys)
&body body)
I am a newbie in Lisp.
I want to access a particular property from a property list with a string variable like this
(setf sym (list :p1 1))
(setf x "p1")
(getf sym :x)
About cl:getf
Let Petit Prince's answer is right that getf is probably the function you want to use here, but note that it can be used for more than just keyword symbols. You can use it for any objects. A property list is just a list of alternating indicators and values, and any object can be an indicator:
(let ((plist (list 'a 'b 'c 'd)))
(getf plist 'c))
;=> D
You can even use strings as indicators:
(let* ((name "p1")
(plist (list name 1)))
(getf plist name))
;=> 1
However, that's probably not great practice, since getf compares indicators with eq. That means that using strings as indicators might not be reliable, depending on your use case:
(let ((plist (list "p1" 1)))
(getf plist "p1"))
;=> NIL
For your example
In your case, you're trying to take a string and find the object for a symbol with a name that's string-equal (i.e., with the same characters, but disregarding case). It probably makes more sense to loop over the list and compare indicators with string-equal.
(let ((plist '(:p1 1 :p2 2)))
(loop
for (indicator value) on plist by #'cddr
when (string-equal indicator "p1")
return value))
;=> 1
And of course, you can wrap that up in a function for abstraction:
(defun getf-string-equal (plist indicator)
(loop
for (i v) on plist by #'cddr
when (string-equal i indicator)
return v))
(getf-string-equal '(:p1 1 :p2 2) "p1")
;=> 1
The second parameter to getf is a keyword, and you have string. A keyword is a symbol that lives in the package KEYWORD and has usually been uppercased by the reader:
? (setf sym (list :p1 1))
(:P1 1)
? sym
(:P1 1)
So you need to use:
? (getf sym (find-symbol (string-upcase x) "KEYWORD"))
1
I have a list of lists as follows in Common Lisp of the form
((1 2) (3 4) (5 6))
and which is the value of the variable list, and I want to have three new variables whose values are the elements of the list. For instance:
list-1 (1 2)
list-2 (3 4)
list-3 (5 6)
Is there any function which does this operation?
Use setq, first (or nth and elt) to set:
(setq list-1 (first list)
list-2 (second list)
list-3 (third list))
Or destructuring-bind to bind:
(destructuring-bind (list-1 list-2 list-3) list
...)
Again, destructuring-bind binds the variables instead of assigning them (i.e., it is like let, not like setq).
The notion of binding elements of a list to names of the form list-# can be generalized.
You can create a function to generate a lambda with the ordinal list names as arguments, and a given body:
(defun make-list-lambda (n body)
(let ((list-names (loop for index from 1 to n
collect (intern (format nil "LIST-~D" index)))))
`(lambda ,list-names
(declare (ignorable ,#list-names))
,#body)))
And then create a macro to create the lambda, compile it, and apply it to the list:
(defmacro letlist (list &body body)
(let ((assignments (gensym)))
`(let ((,assignments ,list))
(apply (compile nil (make-list-lambda (length ,assignments) ',body))
,assignments))))
In this way, the assignments are localized to the lambda body:
CL-USER> (letlist '(a b c d e f)
(format t "list-1: ~A~%" list-1)
(format t "list-3: ~A~%" list-3))
list-1: A
list-3: C
NIL
Note: The forms will be compiled every time the macro is invoked, since it will not be known how many list-# arguments will be present until the list is presented!
First set your list to a variable, for instance mylist. Then spit out the required
output using the function format. I'm using CLISP. Hope this helps. This is the actual REPL output.
(setf mylist '((1 2) (3 4) (5 6)) )
((1 2) (3 4) (5 6))
(format t "list-1 ~d~%list-2 ~d~%list-3 ~d" (car mylist)
(second mylist) (last mylist))
list-1 (1 2)
list-2 (3 4)
list-3 ((5 6))
NIL
[142]>
Can someone show me how to get rid of "NIL' in the above output?
I'm new to Lisp. Just learning for fun.