Destructive sorting in lisp - common-lisp

I'm reading Practical Common Lisp. In chapter 11, it says this about sorting:
Typically you won't care about the unsorted version of a sequence after you've sorted it, so it makes sense to allow SORT and STABLE-SORT to destroy the sequence in the course of sorting it. But it does mean you need to remember to write the following:
(setf my-sequence (sort my-sequence #'string<))
I tried the following code:
CL-USER> (defparameter *a* #( 8 4 3 9 5 9 2 3 9 2 9 4 3))
*A*
CL-USER> *a*
#(8 4 3 9 5 9 2 3 9 2 9 4 3)
CL-USER> (sort *a* #'<)
#(2 2 3 3 3 4 4 5 8 9 9 9 9)
CL-USER> *a*
#(2 2 3 3 3 4 4 5 8 9 9 9 9)
In this code we can see that the variable *a* has been changed by the sort function.
Then why do the book say that is necessary to do an assignment?
I'm using SBCL + Ubuntu 14.04 + Emacs + Slime
EDIT:
Following the comment of #Sylwester I add the evaluation of *a* so it's clear that the value has been changed.

It's necessary to do the assignment if you want your variable to contain the proper value of the sorted sequence afterwards. If you don't care about that and only want the return value of sort, you don't need an assignment.
There are two reasons for this. First, an implementation is allowed to use non-destructive copying to implement destructive operations. Secondly, destructive operations on lists can permute the conses such that the value passed into the operation no longer points to the first cons of the sequence.
Here's an example of the second problem (run under SBCL):
(let ((xs (list 4 3 2 1)))
(sort xs '<)
xs)
=> (4)
If we add the assignment:
(let ((xs (list 4 3 2 1)))
(setf xs (sort xs '<))
xs)
=> (1 2 3 4)

The variable can't be changed by the sort function, since the sort function does not know about the variable at all.
All the sort function gets is a vector or a list, but not variables.
In Common Lisp the sort function can be destructive. When it gets a vector for sorting, it can return the same vector or a new one. This is up to the implementation. In one implementation it might return the same vector and in another one it may return a new one. But in any case they will be sorted.
If there is a variable, which points to a sequence and for which the author expects that it will after sorting point to a sorted sequence: set the variable to the result of the sort operation. Otherwise there might be cases, where after potentially destructive sorting, the variable won't point to the SORT result, but still to an unsorted, or otherwise changed, sequence. In case of the vector this CAN be the old and unsorted vector.
REMEMBER
The only thing you can be sure: the SORT function returns a sorted sequence as its value.

Related

Equality of vectors in clojure

I was trying to solve this problem
https://www.4clojure.com/problem/32
and I realized that this statement gave output as false.
(= (#(into [] (distinct %)) [1 2 3])
'(1 1 2 2 3 3))
It is supposed to be true as the function is also returning the same vector.
Can someone please explain to me why this is false?
The question you ask is irrelevant to the problem you refer to, which your own answer solves. Looking at the question alone ...
As rascio comments, you are applying distinct to the wrong
sequence.
Furthermore, you can apply = to any two sequences. You don't have
to convert the lazy sequence that distinct produces to a vector.
Thus the following suffices ...
(= [1 2 3] (distinct '(1 1 2 2 3 3)))
=> true
From the comments, I found out that I was using the distinct method incorrectly and hence decided to use the repeat method to get the answer which was:
mapcat #(repeat 2 %)

Evaluate the expression CLISP

(+ '(1 2 3 4 5) '(3 4 5 6 7))
Evaluate this expression. I don't know much about CLISP.
It returns an error when I runs it on CLISP.
Explain the reason for error ??
Thanks in advance
It's possible you were expecting this to concatenate
(+ '(1 2 3 4 5) '(3 4 5 6 7)) ==> '(1 2 3 4 5 3 4 5 6 7)
Common Lisp doesn't do this because it wouldn't make sense. In some languages like Python, there are a limited number of infix operators, so overloading + makes a certain amount of sense. However, in Common Lisp, there are infinitely many function names and + is but one of them, so we have different functions, such as append to do this.
It's also possible you were expecting this to add pointwise.
(+ '(1 2 3 4 5) '(3 4 5 6 7)) ==> '(4 6 8 10 12)
It doesn't do this as it's also against Lisp's philosophy. Adding elements pointwise like this is a feature of tacit languages such as APL or J. These languages go to a lot of trouble to get features like this to work in the most general possible cases. As such, they tend not to focus so much on certain other features, such as the object system or metaprogramming.
This is where Lisp shines: Lisp is a metaprogramming language, so rather than spend all their time developing corner cases for mathematical functions, they made a simple function that simply adds numbers together and does nothing more, and then spent the bulk of their development time making a good macro system. Common Lisp in particular adds to this by having one of the best object systems (with fully generic dispatch) that I've seen. Languages aren't good at everything, so the best languages have to define a philosophy and stick to it. Accepting all kinds of input simply isn't Lisp's philosophy; metaprogramming is.
CLISP itself will give you part of the answer:
[1]> (+ '(1 2 3 4 5) '(3 4 5 6 7))
*** - +: (1 2 3 4 5) is not a number
+ is a function that is only defined on numbers, so when the interpreter sees that a list of numbers has been offered as an argument to +, it can't go any further.
The interpreter sees (1 2 3 4 5) as the first argument to + after evaluating '(1 2 3 4 5), i.e. (quote (1 2 3 4 5)), which returns (1 2 3 4 5).
You may be thinking that + is more flexible, sort of like the way that it works in Javascript. No: It's just the math plus function.
(Why doesn't the interpreter complain about (3 4 5 6 7)? Because it stopped when it saw (1 2 3 4 5), and went to the debugger prompt.)
By the way, that error message is CLISP-specific, but any Common Lisp will give you an error on that input.
EDIT: Per #RainerJoswig's comment, it may be that the correct way to describe this is not that interpreter code responds to (1 2 3 4 5) being paired with +, but the + function code that does so, and doesn't bother with the second argument, etc. What I wrote was my best guess about the right way to describe the situation, and partially addresses OP's question, but I am not a Lisp internals expert.

Displaced multidimensional arrays in common lisp

So I have some code that needs a subset of a multidimensional array in such a way that it works a bit more like taking a subsection of a matrix, ideally it would work like a displaced array.
So let's say I have something that looks like this
(defvar *a* (make-array '(3 3) :initial-contents
'((1 2 3) (2 3 1) (3 1 2))
And I want it to be accessible with an array *b*
(defvar *b* (make-array '(2 2) :displaced-to *a* :displaced-index-offset
(array-major-row-index *a* '(1 1)))
Such that *b* will point to
#2a((3 1) (1 2))
instead of
#2a((3 1) (3 1))
I've already written myself a multidimensional slice function that copies the parts of the array I want, but it would be ideal to not need to copy back and forth manually, is there any solution that works like this in vanilla common lisp?
I understand that the way that displaced multidimensional arrays work in a way that coheres directly with (array-major-row-index) (namely that #2a((1 2 3) (2 3 4)) has row indices (0 1 2 3 4 5) and therefore the displaced array at '(1 0) of dimensions '(2 2) will point to #2a((2 3) (2 3)), so I need to wrap the new array such that it refers to specific places in the old one, but so far I don't know how to capture such a reference.
I'm not entirely sure that it is possible to get pointers to places in the array, so I would appreciate if that could be cleared up.
You can't directly do it, but FYI there used to be support for this in Symbolics Lisp Machines.
From Kent Pitman:
What was new with the LispM, and which did not carry into CL (perhaps
because of the lack of microcode assist for speed) was conformally
displaced arrays (I think you said :displaced-conformally t, or some
such) in which case you got a displaced region of the original square
(cube, etc) rather than a region of the linearized storage. This was
useful for displacing to screen memory, especially since the LispM
used DMA (direct memory access) display from a raster array that was,
I think, specially known by the screen to mean "this array's memor IS
the screen" and doing a SETF of AREF into that special array made
something appear on the screen. All windows had conformally displaced
indirect arrays that represented their part of the screen.
As pointed out by Rainer Joswig, there is a video on Youtube, from Kalman Reti, demonstrating conformally displaced arrays. It might be possible for implementations to provide support for this, but I don't know if any current one provides such displaced arrays. But other answers are fine suggesting alternatives.
Multidimensional arrays are stored in memory as a one-dimensional array in row-major order. That is, #2a((1 2 3) (2 3 1) (3 1 2)) is actually the same as #(1 2 3 2 3 1 3 1 2).
CL-USER> (let ((a (make-array '(3 3) :initial-contents
'((1 2 3) (2 3 1) (3 1 2)))))
(make-array 9 :displaced-to a))
#(1 2 3 2 3 1 3 1 2)
A displaced array is a contiguous subset of the actual array (sharing memory with it). Your desired *B* would not be contiguous, since it would have to arbitrarily jump over the last 3 in the array.
*B*
/ \
--- ---
1 2 3 2 3 1 3 1 2
You would have to either include the skipped over 3 in the displaced array, or use two separate displaced arrays.
As explained in the answer of jkiiski you cannot obtain directly what you want, but you could “approximate” such result by using array of arrays, instead of multi-dimensional arrays.
For instance:
(defvar *a* (make-array 3 :initial-contents '(#(1 2 3) #(2 3 1) #(3 1 2))))
and then *b* could be defined as an array whose elements are arrays displaced on the appropriate arrays of *a*:
(defvar *b*
(make-array 2 :initial-contents
(loop for row from 1 to 2
collect (make-array 2 :displaced-to (aref *a1* row) :displaced-index-offset 1))))
The main difference with respect to the multi-dimensional arrays is that instead of using:
(aref *b* 1 1)
you should use:
(aref (aref *b* 1) 1) ; => produces 2 for the example above
And of course you could define macros or reader macros to simplify this notation.

Why is a macro necessary for assigning a symbol's value? [duplicate]

(setf list (loop for i from 1 to 12 collect i))
(defun removef (item seq)
(setf seq (remove item seq)))
CL-USER> (removef 2 list)
(1 3 4 5 6 7 8 9 10 11 12)
CL-USER> (removef 3 list)
(1 2 4 5 6 7 8 9 10 11 12)
Why doesn't removef really modify the variable?
In Common Lisp, parameters are passed "by identity" (this term goes back to D. Rettig, one of the developers of the Allegro Common Lisp implementation). Think of pointers (to heap objects) being passed by values, which is true for most Lisp objects (like strings, vectors, and, of course, lists; things are slightly more complicated, since implementations might also have immediate values, but that's beside the point here).
The setf of seq modifies the (private, lexical) variable binding of the function. This change is not visible outside of removef.
In order for removef to be able to affect the surrounding environment at the point of the call, you need to make it a macro:
(defmacro removef (element place)
`(setf ,place (remove ,element ,place)))
You might want to take at look at setf and the concept of generalized references. Note, that the macro version of removef I provided above is not how it should actually be done! For details, read about get-setf-expansion and its ugly details.
If all you want to do is to destructively modify the list, consider using delete instead of remove, but be aware, that this might have unintended consequences:
(delete 2 '(1 2 3 4))
is not allowed by the ANSI standard (you are destructively modifying a literal object, i.e., part of your code). In this example, the mistake is easy to spot, but if you are 7 frames deep in some callstack, processing values whose origin is not entirely clear to you, this becomes a real problem. And anyway, even
(setf list (list 1 2 3 4))
(delete 1 list)
list
might be surprising at first, even though
(setf list (list 1 2 3 4))
(delete 2 list)
list
seems to "work". Essentially, the first example does not work as intended, as the function delete has the same problem as your original version of removef, namely, it cannot change the caller's notion of the list variable, so even for the destructive version, the right way to do it is:
(setf list (delete 1 (list 1 2 3 4)))
Here is an example of an implementation of removef that is "able to affect the surrounding environment at the point of the call", as stated by #Dirk.
(defmacro removef (item place &rest args &key from-end test test-not start end count key &environment env)
(declare (ignore from-end test test-not start end count key))
(multiple-value-bind (vars vals store-vars writer-form reader-form)
(get-setf-expansion place env)
(assert (length= store-vars 1) ()
"removef only supports single-value places")
(let ((v.args (make-gensym-list (length args)))
(store-var (first store-vars)))
(once-only (item)
`(let* (,#(mapcar #'(lambda (var val)
`(,var ,val))
vars vals)
,#(mapcar #'(lambda (v.arg arg)
`(,v.arg ,arg))
v.args args)
(,store-var (remove ,item ,reader-form ,#v.args)))
,writer-form)))))
The utilities length= , make-gensym-list and once-only are available at Project Alexandria.
BTW exists at Alexandria a removef definition that uses define-modify-macro but requires an auxiliary definition. This version does not requires an auxiliary defintion.

What determines when a collection is created?

If I understand correctly Clojure can return lists (as in other Lisps) but also vectors and sets.
What I don't really get is why there's not always a collection that is returned.
For example if I take the following code:
(loop [x 128]
(when (> x 1)
(println x)
(recur (/ x 2))))
It does print 128 64 32 16 8 4 2. But that's only because println is called and println has the side-effect (?) of printing something.
So I tried replacing it with this (removing the println):
(loop [x 128]
(when (> x 1)
x
(recur (/ x 2))))
And I was expecting to get some collecting (supposedly a list), like this:
(128 64 32 16 8 4 2)
but instead I'm getting nil.
I don't understand which determines what creates a collection and what doesn't and how you switch from one to the other. Also, seen that Clojure somehow encourages a "functional" way of programming, aren't you supposed to nearly always return collections?
Why are so many functions that apparently do not return any collection? And what would be an idiomatic way to make these return collections?
For example, how would I solve the above problem by first constructing a collection and then iterating (?) in an idiomatic way other the resulting list/vector?
First I don't know how to transform the loop so that it produces something else than nil and then I tried the following:
(reduce println '(1 2 3))
But it prints "1 2nil 3nil" instead of the "1 2 3nil" I was expecting.
I realize this is basic stuff but I'm just starting and I'm obviously missing basic stuff here.
(P.S.: retag appropriately, I don't know which terms I should use here)
A few other comments have pointed out that when doesn't really work like if - but I don't think that's really your question.
The loop and recur forms create an iteration - like a for loop in other languages. In this case, when you are printing, it is indeed just for the side effects. If you want to return a sequence, then you'll need to build one:
(loop [x 128
acc []]
(if (< x 1)
acc
(recur (/ x 2)
(cons x acc))))
=> (1 2 4 8 16 32 64 128)
In this case, I replaced the spot where you were calling printf with a recur and a form that adds x to the front of that accumulator. In the case that x is less than 1, the code returns the accumulator - and thus a sequence. If you want to add to the end of the vector instead of the front, change it to conj:
(loop [x 128
acc []]
(if (< x 1)
acc
(recur (/ x 2)
(conj acc x))))
=> [128 64 32 16 8 4 2 1]
You were getting nil because that was the result of your expression -- what the final println returned.
Does all this make sense?
reduce is not quite the same thing -- it is used to reduce a list by repeatedly applying a binary function (a function that takes 2 arguments) to either an initial value and the first element of a sequence, or the first two elements of the sequence for the first iteration, then subsequent iterations are passed the result of the previous iteration and the next value from the sequence. Some examples may help:
(reduce + [1 2 3 4])
10
This executes the following:
(+ 1 2) => 3
(+ 3 3) => 6
(+ 6 4) => 10
Reduce will result in whatever the final result is from the binary function being executed -- in this case we're reducing the numbers in the sequence into the sum of all the elements.
You can also supply an initial value:
(reduce + 5 [1 2 3 4])
15
Which executes the following:
(+ 5 1) => 6
(+ 6 2) => 8
(+ 8 3) => 11
(+ 11 4) => 15
HTH,
Kyle
The generalized abstraction over collection is called a sequence in Clojure and many data structure implement this abstraction so that you can use all sequence related operations on those data structure without thinking about which data structure is being passed to your function(s).
As far as the sample code is concerned - the loop, recur is for recursion - so basically any problem that you want to solve using recursion can be solved using it, classic example being factorial. Although you can create a vector/list using loop - by using the accumulator as a vector and keep appending items to it and in the exist condition of recursion returning the accumulated vector - but you can use reductions and take-while functions to do so as shown below. This will return a lazy sequence.
Ex:
(take-while #(> % 1) (reductions (fn [s _] (/ s 2)) 128 (range)))

Resources