So I am going through Practical Common Lisp once again and I cannot really understand how to create a vector with constant size.
According to the book:
However, even a vector with a fill pointer isn't completely resizable. The vector *x* can hold at most five elements. To make an arbitrarily resizable vector, you need to pass MAKE-ARRAY another keyword argument: :adjustable.
However when I use (vector-push-extend) I can extend my initial vector even when I set :adjustable nil (or leave it default).
(vector-push 'a *x*) ;; 0
(vector-push 'b *x*) ;; 1
(vector-push 'c *x*) ;; 2
(vector-push 'd *x*) ;; 3
(vector-push 'e *x*) ;; 4
*x* ;; #(A B C D E)
(vector-push 'f *x*) ;; NIL
*x* ;; #(A B C D E)
(vector-push-extend 'f *x*) ;; 5
*x* ;; #(A B C D E F)
I assumed that (vector-push-extend) cannot resize array which is not :adjustable? What is the correct way of creating non-dynamic (non-adjustable) array?
The behavior is implementation specific.
The Common Lisp specification says:
There is no specified way to create an array for which adjustable-array-p definitely returns false.
An implementation may make vectors adjustable, even though the :adjustable argument to make-array is given as nil.
To see if an array object is actually adjustable, one needs to call adjustable-array-p.
The Common Lisp standard says that a vector is expressly adjustable (and thus also actually adjustable if it was requested to be so. If it wasn't request, the vector can still be adjustable, actually adjustable.
So the :adjustable nil arg is just telling Lisp, that it can make the vector non-adjustable, if possible.
Here in SBCL:
1) A normal vector is not adjustable:
* (make-array 5)
#(0 0 0 0 0)
* (adjustable-array-p *)
NIL
2) A vector with a fill-pointer is actually adjustable in SBCL:
* (make-array 5 :fill-pointer 0)
#()
* (adjustable-array-p *)
T
3) A vector with a fill-pointer is actually adjustable in SBCL, even though the :adjustable arg was given as nil:
* (make-array 5 :fill-pointer 0 :adjustable nil)
#()
* (adjustable-array-p *)
T
That's in SBCL. In LispWorks 2) and 3) would not be actually adjustable.
The specification of make-array says that it is implementation dependent whether an array with :adjustable nil is actually adjustable. In the notes, it goes on to say:
There is no specified way to create an array for which adjustable-array-p definitely returns false.
So, it really depends on the implementation.
The correct way is to use vector-push if you do not want to extend.
Related
I am trying to write an fx in lisp to tell if an object ends in nil.
(setq isList (lambda (listOfValues)
(if (null listOfValues) t)
( funcall isList (cdr listOfValues) )
)
)
However, I am having trouble checking if its nil in all cases. In particular, cdr would fail at last elt if it is not a list. How can I resolve this?
Before we get closer to answer your actual question, a few things. First, use defun to define functions, not "set a variable to a lambda", it will make you happier down the line. Second, Common Lisp style would vale been one of values, list-of-values, or just list (that would indicate we knew it was a list, so I would probably just have gone with values here), not "listOfValues" (case is typically smashed, and neither "listofvalues" nor "LISTOFVALUES" are easy to read).
So, back to the code. A list is composed of cons cells, of either atoms or other cons cells. We have two test functions, either consp or atom that would be useful in this case. We know that if we're looking at a cons, we need to recurse on its cdr, otherwise we're at the last element and can just check if we're looking at nil.
(defun is-proper-list (values)
(if (consp values)
(is-proper-list (cdr values))
(null values))) ;; We could do this test as (eql nil) as well
It can be done faster with
(defun listp (l)
(tailp nil l))
(tailp nil ...) tests, whether nil is the end of a given object after cdr-ing to the end.
tailp is a very special function. So don't use it without understanding it.
(tailp '(b c) '(a b c)) is e.g. NOT T, because '(b c) is not the same object like the ( ... b c). But in this case, because NIL is '() and is unique in Lisp, any nil is object-identical. Therefore one can use tailp here for this specific test, whether a given list ends with NIL.
listp is a lisp-convention conform name for this.
(predicate functions returning booleans ending with p for predicate.
Since no - used in the name, attach p without - otherwise attach -p).
(tailp (cdr '(a b c)) '(a b c)) ;; NIL
;; because the two lists are not object-identical
(setq l '(a b c))
(tailp (cddr l) l) ;; T ;; object-identical
thanks for your support, I am a newbie...
I would like to swap elements BETWEEN two lists in Common-LISP given a certain index of the first and second list, for example:
(1 2 3 4) (A B C D) -> (D 2 3 4) when specified indexes are (0 3).
It might look randomish but it has a nice utility in musical sequences...
Thanks,
Alessandro
If you need to use an index, maybe a vector can be more sensible. Use for example ROTATEF, as explained by jkiiski:
CL-USER> (let ((a (vector 1 2 3 4))
(b (vector 'a 'b 'c 'd)))
(rotatef (aref a 0) (aref b 3))
(values a b))
#(D 2 3 4)
#(A B C 1)
If you really want to use lists, then use NTH, or ELT, which works on both kinds of sequences.
Preemptive remark: you cannot modify constant data. Note how vectors a and b are allocated at runtime. Constant data is data that was computed at read-time or compile-time, and should not be modified at runtime. Quoted lists are constant, as shown by this example:
CL-USER> (let ((list '(a b))) (setf (first list) 0) list)
; in: LET ((LIST '(A B)))
; (SETF (FIRST LIST) 0)
; ==>
; (SB-KERNEL:%RPLACA LIST 0)
;
; caught WARNING:
; Destructive function SB-KERNEL:%RPLACA called on constant data: (A B).
; See also:
; The ANSI Standard, Special Operator QUOTE
; The ANSI Standard, Section 3.2.2.3
;
In Clojure, the square brackets are a shorthand for defining vectors:
user=> (vector 'a 'b 'c)
[a b c]
user=> ['a 'b 'c]
[a b c]
The documentation page for vector speaks of the long way and the short way of defining vectors.
However, in defn and doseq there seems to be a difference.
user=> (doseq [x (range 1 4)] (printf "%d\n" x))
1
2
3
nil
user=> (doseq (vector 'x (range 1 4)) (printf "%d\n" x))
IllegalArgumentException doseq requires a vector for its binding in user:1 clojure.core/doseq (core.clj:2935)
What accounts for this difference? Are the square brackets given special status in the reader, or do they sugar some particular form?
vector is evaluated after macroexpansion, while [] is evaluated at read time, before macros are expanded. In your second case, the doseq macro does not see a vector, it sees a list starting with the symbol vector, since macros are expanded before regular functions are evaluated.
I am trying to make a node object in Common Lisp using SBCL that is initialized with its text element and then has links to other nodes. My function link is supposed to take node "from_node", get its member links (which should be a mutable/extendable vector) and push in the node "to_node".
I compile say.lisp, create 2 global variables that represent nodes and then try to link the two nodes. I am getting an error
Here is say.lisp
(defclass node ()
((text
:initarg :text)
(links
:initform (make-array 1 :adjustable t))))
(defun link (from_node to_node)
(vector-push-extend to_node (slot-value from_node 'links)))
And then in the REPL
* (load "say.lisp")
T
* (defvar *x* (make-instance 'node :text "hello world"))
*X*
* (defvar *y* (make-instance 'node :text "bye world"))
*Y*
* (link *x* *y*)
debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {1003016593}>:
The value #() is not of type (AND VECTOR (NOT SIMPLE-ARRAY)).
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(VECTOR-PUSH-EXTEND #<NODE {10031D3983}> #() NIL)
0]
Originally I thought that I was making an immutable vector, but ":adjustable t" should allow this to work.
What is wrong?
VECTOR-PUSH-EXTEND requires that the vector argument is a "vector with a fill pointer." Passing :adjustable t to the make-array makes it adjustable, but doesn't give it a fill pointer. For instance, without a fill pointer:
CL-USER> (defparameter *x* (make-array 1 :adjustable t))
*X*
CL-USER> *x*
#(0)
CL-USER> (vector-push-extend 3 *x*)
; Evaluation aborted on #<SIMPLE-TYPE-ERROR expected-type:
(AND VECTOR (SATISFIES ARRAY-HAS-FILL-POINTER-P))
datum: #<(VECTOR T 1) {100464C57F}>>.
With a fill pointer:
CL-USER> (defparameter *x* (make-array 1 :adjustable t :fill-pointer 0))
*X*
CL-USER> *x*
#()
CL-USER> (vector-push-extend 3 *x*)
0
CL-USER> (vector-push-extend 4 *x*)
1
CL-USER> (vector-push-extend 5 *x*)
2
CL-USER> *x*
#(3 4 5)
It's an important difference because you can have adjustable arrays without fill pointers, as you've seen. These can be resized, but always appear to have as many elements as there is space. (E.g., in the first case, *x* has length one. You can also have arrays will fill pointers that are not adjustable. These would still allow you to use vector-push and vector-push-extend until they were filled up, but couldn't be resized afterward.
I think I just use setq (or setf, I'm not really sure the difference), but I don't understand how to reference the [i][j]-th element in an array in lisp.
My start condition is this:
? (setq x (make-array '(3 3)))
#2A((0 0 0) (0 0 0) (0 0 0))
I want to alter, say, the 2nd item of the 3rd "row" to give this:
? ;;; What Lisp code goes here?!
#2A((0 0 0) (0 0 0) (0 "blue" 0))
The following, which I would have thought close, gives an error:
(setq (nth 1 (nth 2 x)) "blue")
So what's the correct syntax?
Thanks!
I think proper way is to use setf with aref like this:
(setf (aref x 2 1) "blue")
For more details see reference.
You can find a dictionary of the ARRAY operations in the Common Lisp HyperSpec (the web version of the ANSI Common Lisp standard:
http://www.lispworks.com/documentation/lw50/CLHS/Body/c_arrays.htm
AREF and (SETF AREF) are documented here:
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_aref.htm
The syntax to set an array element is: (setf (aref array &rest subscripts) new-element).
Basically if you want to set something in Common Lisp, you just need to know how to get it:
(aref my-array 4 5 2) ; access the contents of an array at 4,5,2.
Then the set operation is schematically:
(setf <accessor code> new-content)
This means here:
(setf (aref my-array 4 5 2) 'foobar) ; set the content of the array at 4,5,2 to
; the symbol FOOBAR
The correct invocation is
(setf (aref x 2 1) "blue")
setq is used when you're assigning to a variable. Only setf knows how to "reach into" compound objects as with setting a value in your array. Of course, setf also knows how to assign to variables, so if you stick with setf you'll always be okay.