I'm trying to write a function that will destructively remove N elements from a list and return them. The code I came up with (see below) looks fine, except the SETF is not working the way I intended.
(defun pick (n from)
"Deletes (destructively) n random items from FROM list and returns them"
(loop with removed = nil
for i below (min n (length from)) do
(let ((to-delete (alexandria:random-elt from)))
(setf from (delete to-delete from :count 1 :test #'equal)
removed (nconc removed (list to-delete))))
finally (return removed)))
For most cases, this works just fine:
CL-USER> (defparameter foo (loop for i below 10 collect i))
CL-USER> (pick 3 foo)
(1 3 6)
CL-USER> foo
(0 2 4 5 7 8 9)
CL-USER> (pick 3 foo)
(8 7 0)
CL-USER> foo
(0 2 4 5 9)
As you can see, PICK works just fine (on SBCL) unless the element being picked happens to be the first on the list. In that case, it doesn't get deleted. That's because the only reassignment happening is the one that goes on inside DELETE. The SETF doesn't work properly (i.e. if I use REMOVE instead, FOO does not change at all).
Is there any scoping rule going on that I'm not aware of?
A (proper) list consists of cons cells that each hold a reference to the next
cell. So, it is actually a chain of references, and your variable has a
reference to the first cell. To make this clear, I rename the binding outside
of your function to var:
var ---> [a|]--->[b|]--->[c|nil]
When you pass the value of the variable to your function, the parameter gets
bound to the same reference.
var ---> [a|]--->[b|]--->[c|nil]
/
from --'
You can update the references in the chain, for example eliminate b:
var ---> [a|]--->[c|nil]
/
from --'
This has an effect on the list that var sees outside.
If you change the first reference, for example eliminating a, this is just the
one originating from from:
var ---> [a|]--->[b|]--->[c|nil]
/
from --'
This has obviously no effect on what var sees.
You need to actually update the variable binding in question. You can do that
by setting it to a value returned by function. Since you already return a
different value, this would then be an additional return value.
(defun pick (n list)
(;; … separate picked and rest, then
(values picked rest)))
Which you then use like this, for example:
(let ((var (list 1 2 3)))
(multiple-value-bind (picked rest) (pick 2 var)
(setf var rest)
(do-something-with picked var)))
Now to the separation: unless the list is prohibitively long, I'd stick to
non-destructive operations. I also would not use random-elt, because it needs
to traverse O(m) elements each time (m being the size of the list),
resulting in a runtime of O(n·m).
You can get O(m) overall runtime by determining the current chance of picking
the current item while linearly running over the list. You then collect the
item into either the picked or rest list.
(defun pick (n list)
(loop :for e :in list
:and l :downfrom (length list)
:when (or (zerop n)
(>= (random 1.0) (/ n l)))
:collect e :into rest
:else
:collect e :into picked
:and :do (decf n)
:finally (return (values picked rest))))
Delete isn't required to modify any structure, it's just permitted to. In fact, you can't always do a destructive delete. If you wanted to delete 42 from (42), you'd need to return the empty list (), which is the symbol NIL, but there's no way that you can turn the list (42), which is a cons cell (42 . NIL) into a different type of object (the symbol NIL). As such, you'll probably need to return both the updated list, as well as the elements that were removed. You can do that with something like this, which returns multiple values:
(defun pick (n from)
(do ((elements '()))
((or (endp from) (zerop n))
(values elements from))
(let ((element (alexandria:random-elt from)))
(setf from (delete element from)
elements (list* element elements))
(decf n))))
CL-USER> (pick 3 (list 1 2 3 2 3 4 4 5 6))
(2 6 4)
(1 3 3 5)
CL-USER> (pick 3 (list 1 2 3 4 5 6 7))
(2 7 5)
(1 3 4 6)
CL-USER> (pick 2 (list 1 2 3))
(2 3)
(1)
CL-USER> (pick 2 (list 1))
(1)
NIL
On the receiving end, you'll want to use something like multiple-value-bind or multiple-value-setq:
(let ((from (list 1 2 3 4 5 6 7)))
(multiple-value-bind (removed from)
(pick 2 from)
(format t "removed: ~a, from: ~a" removed from)))
; removed: (7 4), from: (1 2 3 5 6)
(let ((from (list 1 2 3 4 5 6 7))
(removed '()))
(multiple-value-setq (removed from) (pick 2 from))
(format t "removed: ~a, from: ~a" removed from))
; removed: (3 5), from: (1 2 4 6 7)
delete does not necessarily modify its sequence argument. As the hyperspec says:
delete, delete-if, and delete-if-not return a sequence of the same type as sequence that has the same elements except that those in the subsequence bounded by start and end and satisfying the test have been deleted. Sequence may be destroyed and used to construct the result; however, the result might or might not be identical to sequence.
For instance, in SBCL:
* (defvar f (loop for i below 10 collect i))
F
* (defvar g (delete 0 f :count 1 :test #'equal))
G
* g
(1 2 3 4 5 6 7 8 9)
* f
(0 1 2 3 4 5 6 7 8 9)
*
Note that in your function setf modifies the local variable from, and since delete in the case of first element does not modify the original list, at the end of the function the variable foo maintains the old values.
Related
I am familiar with how to set elements in a 2D array, which can be done using the following statement.
(setf (aref array2D 0 0) 3)
However, I am not familiar how to set elements in a list of lists, such as the following input: '((1) (2) (2) (1)). I can't use aref, since it only works on arrays.
As mentioned, while aref works on arrays, elt works on sequences which can be:
an ordered collection of elements
a vector or a list.
* (setf test-list '((1) (2) (2) (1)))
((1) (2) (2) (1))
* (setf (elt test-list 2) 'hi)
HI
* test-list
((1) (2) HI (1))
You can indeed use variables in place of fixed offsets:
* (setf test-list '((1) (2) (2) (1)))
((1) (2) (2) (1))
* (setf offset 2)
2
* (setf (elt test-list offset) 'hi)
HI
* test-list
((1) (2) HI (1))
To access the nth element of a list, there are (at least) two functions: nth and elt. The order of the parameters is different, and nth only work on lists while elt works on any sequence (i.e. lists, vector, strings ...):
(nth 1 '(foo bar baz)) => BAR
(nth 1 #(foo bar baz)) => ERROR
(elt '(foo bar baz) 1) => BAR
(elt #(foo bar baz) 1) => BAR
Now, in general, the way to set a value (as opposed to simply access it) is very straightforward, and at least for built-in functions this is almost always the case: whenever you have some form FORM which retrieves some value from what is called a place, the form (setf FORM <value>) will set this element to the given <value>. This works for functions such as car, cdr, gethash, aref, slot-value, symbol-function and many others, and any combination of those.
In your example, you have a list of lists. So, for example, to modify the "inner integer" in say the third list:
* (setf test-list '((0) (1) (2) (3))) ; changed the values to have something clearer
((0) (1) (2) (3))
* (car (nth 2 test-list)) ; this accesses the integer in the second list
2
* (setf (car (nth 2 test-list)) 12) ; this modifies it. Notice the syntax
12
* test-list
((0) (1) (12) (3))
On a side note, you should avoid modifying literal lists (created using the quote symbol '). If you want to modify lists, create them at runtime using the list function.
EDIT:
What happens is that setf knows, by "looking" at the form you give it, how to actually find the place that you want to modify, potentially using functions in this process.
If you look at other languages, such as Python, you also have some kind of duality in the syntax used both to get and to set values. Indeed, if you have a list L or a dictionary d, then L[index] and d[thing] will get the corresponding element while L[index] = 12 and d[thing] = "hello" will modify it.
However, in Python, those accessors use a special syntax, namely, the squares brackets []. Other types of objects use another syntax, for example, the dot notation to access slots/attributes of an object as in my-object.attr. A consequence is that the following code is invalid in Python:
>>> L = [1, 2, 3, 2, 1]
>>> max(L)
3
>>> max(L) = 12
Traceback (most recent call last):
File "<string>", line 9, in __PYTHON_EL_eval
File "/usr/lib/python3.8/ast.py", line 47, in parse
return compile(source, filename, mode, flags,
File "<string>", line 1
SyntaxError: cannot assign to function call
You have to write an other function, for example, setMax(L, val), to change the maximum of a list. This means that you now have to functions, and no symmetry anymore.
In Common Lisp, everything is (at least syntactically) a function call. This means that you can define new ways to access and modify things, for any function ! As a (bad) example of what you could do:
* (defun my-max (list)
(reduce #'max list))
MY-MAX
* (my-max '(1 2 3 8 4 5))
8
* (defun (setf my-max) (val list)
(do ((cur list (cdr cur))
(cur-max list (if (< (car cur-max) (car cur))
cur
cur-max)))
((endp (cdr cur)) (setf (car cur-max) val))))
(SETF MY-MAX)
* (setf test-list (list 0 4 5 2 3 8 6 3))
(0 4 5 2 3 8 6 3)
* (setf (my-max test-list) 42)
42
* test-list
(0 4 5 2 3 42 6 3)
This way, the syntax used to both set and get the maximum of a list is identical (FORM to get, (setf FORM val) to set), and combines automatically with every other "setter". No explicit pointers/references involved, it's just functions.
i would like to visit all the cons cells in a list and perform some action on them (including such things as setcar). is there an idiomatic way of doing this?
i can, i think, do something like this
(progn
(setq a (list 1 2 3 4 5 6))
(setq okay a)
(while okay
(if (eq (car okay) 3)
(setcar okay 22))
(setq okay (cdr okay))))
(where the if expression is my "application logic", say.)
but, if there's a terser way of doing this, i'd be interested in hearing about it.
If you want to mutate the cars of the list, then in recent emacsen the likely think you want is cl-mapl, which maps a function over successive tails of the list. This is essentially Common Lisp's mapl function: CL has
maplist which maps a function over tails and returns a new list of the values of the function, so (maplist (lambda (e) e) '(1 2 3)) is ((1 2 3) (2 3) (3));
mapl which is like maplist but returns the original list.
elisp (courtesy of some now-standard library) now has both cl-mapl and cl-maplist.
So:
> (let ((y (list 1 2 3 4 5 6 7)))
(cl-mapl (lambda (tail)
(rplaca tail 0))
y)
y)
(0 0 0 0 0 0 0)
or
> (let ((y (list 1 2 3 4 5 6 7)))
(cl-mapl (lambda (tail)
(rplaca tail (if (cdr tail) (cadr tail) 'fish)))
y)
y)
(2 3 4 5 6 7 fish)
(In neither of these cases do you need to make sure that y is returned: I just did it to make it clear that y is being destructively modified by this.)
(setq a (mapcar (lambda (x) (if (equal x 3) 22 x)) a))
That sets the value of variable a to the result of changing any members of a that are 3 to 22.
Choose the equality operator you want, equal, eql, or =, depending on whether you know that either all list members are numbers (use =) or you know that they are either numbers or you want to test object equality otherwise, (use eql), or you don't know what they might be (use equal).
You haven't indicated any need to do list-structure modification (setcar). It appears that all you care about is for a to be a list as I described.
I can't figure out on how to write a vector function that returns the first odd number in the list.
Ex: (check-expect (first-oddnumb 2 3 4 5 6) 3)) ;;it returns 3 because 3 is the first odd number in the list.
I can't figure out on how to write a vector function that returns the first odd number in the list.
My confusion is the same as #Sylwester's: "vector function"? The rest of the question seems to make sense tho.
I can help you write a function that returns the first odd number in the list.
We want the function to work like this
(first-odd-number 2 3 4 5 6) ;; => 3
So the first thing we have to do is learn how to write a function that accepts a variable number of arguments
(define (variadic . xs) xs)
(variadic 1 2) ;; => '(1 2)
(variadic 1 2 3) ;; => '(1 2 3)
(variadic 1 2 3 4) ;; => '(1 2 3 4)
(variadic) ;; => '()
Note the . before the xs parameter. This gives us a way to collect all of the passed arguments into the bound identifier, xs. Notice how the arguments are collected into a list. Also pay attention to how xs will still be a list (empty list '()) even if no arguments are given in the function call.
Now we can begin writing your function
(define (first-odd-number . xs)
;; so we know xs will be a list here ...
)
Let's talk about the possible states of xs
xs could be empty, in which case what should we return? maybe a 0 or something? (more on this later)
Otherwise, xs has at least one number ...
is the first number an odd number? if so, return that number
is the first number an even number? if so, return first-odd-number of the remaining numbers in xs
OK, we can pretty much define this in Racket verbatim
(define (first-odd-number . xs)
;; begin case analysis of xs
(cond
;; is the list of numbers empty? return 0
[(empty? xs) 0]
;; the list is not empty, continue ...
;; is the first number odd?
[(odd? (car xs)) (car xs)]
;; otherwise...
;; the number even, check remaining numbers
[else (apply first-odd-number (cdr xs))]))
(first-odd-number 2 3 4 5 6) ;; => 3
(first-odd-number 3 4 5 6) ;; => 3
(first-odd-number 4 5 6) ;; => 5
(first-odd-number) ;; => 0
And that's pretty much it !
Improvements...
If you're like me tho, that 0 is making you feel uneasy. What if you were given a list of only even numbers? What should the return value be?
(first-odd-number 2 4 6) ;; => 0
This is kind of weird. We could use the 0 to mean that no odd number was found, but Maybe there's a better way ...
(struct Just (value) #:transparent)
(struct None () #:transparent)
(define (first-odd-number . xs)
(cond
;; no odd number was found; return None
[(empty? xs) (None)]
;; an odd number was found, return (Just n)
[(odd? (car xs)) (Just (car xs))]
;; otherwise check the remaining numbers
[else (apply first-odd-number (cdr xs))]))
(first-odd-number 2 3 4 5 6) ;; => (Just 3)
(first-odd-number 3 4 5 6) ;; => (Just 3)
(first-odd-number 4 5 6) ;; => (Just 5)
(first-odd-number) ;; => (None)
Now when the caller of our first-odd-number is working with the function, we don't have to don't have to remember that 0 is a special case we need to consider
(define (print-the-first-odd-number . xs)
(match (apply first-odd-number xs)
[(Just x) (printf "the number is ~a\n" x)]
[(None) (printf "no odd number was found\n")]))
(print-the-first-odd-number 2 3 4 5 6) ;; the number is 3
(print-the-first-odd-number 2 4 6) ;; no odd number was found
Another way is to use a comprehension to iterate over the vector (or whatever), specifically, for/first, which returns the value returned by the first body that gets evaluated, combined with a #:when clause to limit said evaluation to the first odd element of a vector:
#lang racket/base
(define (first-odd-number container)
(for/first ([num container]
#:when (odd? num))
num))
(displayln (first-odd-number #(2 3 4 5 6))) ; 3, passing a vector
(displayln (first-odd-number '(2 3 4 5 6))) ; 3, passing a list
If no odd number is present, it returns #f.
While you get better performance by using type specific sequence builders like in-vector with a for loop, using a container directly like this gives more flexibility (It would also work with sets of numbers and a few other standard types)
If instead wanting a function that takes a variable number of arguments, use a hardcoded in-list and the appropriate formals:
(define (first-odd-number . numbers)
(for/first ([num (in-list numbers)]
#:when (odd? num))
num))
I am struggling to find the right approach to solve the following function
(FOO #'– '(1 2 3 4 5))
=> ((–1 2 3 4 5) (1 –2 3 4 5) (1 2 –3 4 5) (1 2 3 –4 5) (1 2 3 4 –5))
The first Parameter to the foo function is supposed to be a function "-" that has to be applied to each element returning a list of list as shown above. I am not sure as to what approach I can take to create this function. I thought of recursion but not sure how I will preserve the list in each call and what kind of base criteria would I have. Any help would be appreciated. I cannot use loops as this is functional programming.
It's a pity you cannot use loop because this could be elegantly solved like so:
(defun foo (fctn lst)
(loop
for n from 0 below (length lst) ; outer
collect (loop
for elt in lst ; inner
for i from 0
collect (if (= i n) (funcall fctn elt) elt))))
So we've got an outer loop that increments n from 0 to (length lst) excluded, and an inner loop that will copy verbatim the list except for element n where fctn is applied:
CL-USER> (foo #'- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
Replacing loop by recursion means creating local functions by using labels that replace the inner and the outer loop, for example:
(defun foo (fctn lst)
(let ((len (length lst)))
(labels
((inner (lst n &optional (i 0))
(unless (= i len)
(cons (if (= i n) (funcall fctn (car lst)) (car lst))
(inner (cdr lst) n (1+ i)))))
(outer (&optional (i 0))
(unless (= i len)
(cons (inner lst i) (outer (1+ i))))))
(outer))))
Part of the implementation strategy that you choose here will depend on whether you want to support structure sharing or not. Some of the answers have provided solutions where you get completely new lists, which may be what you want. If you want to actually share some of the common structure, you can do that too, with a solution like this. (Note: I'm using first/rest/list* in preference to car/car/cons, since we're working with lists, not arbitrary trees.)
(defun foo (operation list)
(labels ((foo% (left right result)
(if (endp right)
(nreverse result)
(let* ((x (first right))
(ox (funcall operation x)))
(foo% (list* x left)
(rest right)
(list* (revappend left
(list* ox (rest right)))
result))))))
(foo% '() list '())))
The idea is to walk down list once, keeping track of the left side (in reverse) and the right side as we've gone through them, so we get as left and right:
() (1 2 3 4)
(1) (2 3 4)
(2 1) (3 4)
(3 2 1) (4)
(4 3 2 1) ()
At each step but the last, we take the the first element from the right side, apply the operation, and create a new list use revappend with the left, the result of the operation, and the rest of right. The results from all those operations are accumulated in result (in reverse order). At the end, we simply return result, reversed. We can check that this has the right result, along with observing the structure sharing:
CL-USER> (foo '- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
By setting *print-circle* to true, we can see the structure sharing:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((l '(1 2 3 4 5)))
(list l (foo '- l)))
((1 . #1=(2 . #2=(3 . #3=(4 . #4=(5))))) ; input L
((-1 . #1#)
(1 -2 . #2#)
(1 2 -3 . #3#)
(1 2 3 -4 . #4#)
(1 2 3 4 -5)))
Each list in the output shares as much structure with the original input list as possible.
I find it easier, conceptually, to write some of these kind of functions recursively, using labels, but Common Lisp doesn't guarantee tail call optimization, so it's worth writing this iteratively, too. Here's one way that could be done:
(defun phoo (operation list)
(do ((left '())
(right list)
(result '()))
((endp right)
(nreverse result))
(let* ((x (pop right))
(ox (funcall operation x)))
(push (revappend left (list* ox right)) result)
(push x left))))
The base case of a recursion can be determined by asking yourself "When do I want to stop?".
As an example, when I want to compute the sum of an integer and all positive integers below it, I can do this recusively with a base case determined by answering "When do I want to stop?" with "When the value I might add in is zero.":
(defun sumdown (val)
(if (zerop val)
0
(+ (sumdown (1- val)) val)))
With regard to 'preserve the list in each call', rather than trying to preserve anything I would just build up a result as you go along. Using the 'sumdown' example, this can be done in various ways that are all fundamentally the same approach.
The approach is to have an auxiliary function with a result argument that lets you build up a result as you recurse, and a function that is intended for the user to call, which calls the auxiliary function:
(defun sumdown1-aux (val result)
(if (zerop val)
result
(sumdown1-aux (1- val) (+ val result))))
(defun sumdown1 (val)
(sumdown1-aux val 0))
You can combine the auxiliary function and the function intended to be called by the user by using optional arguments:
(defun sumdown2 (val &optional (result 0))
(if (zerop val)
result
(sumdown2 (1- val) (+ val result))))
You can hide the fact that an auxiliary function is being used by locally binding it within the function the user would call:
(defun sumdown3 (val)
(labels ((sumdown3-aux (val result)
(if (zerop val)
result
(sumdown3-aux (1- val) (+ val result)))))
(sumdown3-aux val 0)))
A recursive solution to your problem can be implemented by answering the question "When do I want to stop when I want to operate on every element of a list?" to determine the base case, and building up a result list-of-lists (instead of adding as in the example) as you recurse. Breaking the problem into smaller pieces will help - "Make a copy of the original list with the nth element replaced by the result of calling the function on that element" can be considered a subproblem, so you might want to write a function that does that first, then use that function to write a function that solves the whole problem. It will be easier if you are allowed to use functions like mapcar and substitute or substitute-if, but if you are not, then you can write equivalents yourself out of what you are allowed to use.
For example, I have a list:
(setq foo '(1 2 3 4 5))
Then I need to get a pointer to its 3rd index element (which contains 4 in the example):
(setq p (SOME_FUNCTION foo 3))
The element with p address can be moved to another list so I can't just save its current foo's index.
And I need to be able to say later on:
(push 0 foo)
=> (0 1 2 3 4 5)
(setf p 444)
and list foo must be (0 1 2 3 444 5) afterwards.
Is this possible in Emacs lisp?
In general, you can't store the "address" of an object. However, you can refer to a cons cell (a cons cell is what lists are made of). The cons cell could later be modified using setcar and setcdr.
For example:
(defvar my-cons-cell nil)
(defun my-save-cons-cell (cons-cell)
(setq my-cons-cell cons-cell))
(defun my-set-car-in-saved-cons-cell (value)
(setcar my-cons-cell value))
;; Test
(setq foo '(1 2 3 4 5))
(my-save-cons-cell (cdr (cdr (cdr foo))))
(push 0 foo)
(my-set-car-in-saved-cons-cell 444)
Here, foo has the value (0 1 2 3 444 5).
Note that this is really un-lisp like and breaks the functional programming paradigm...
You can do
(setq p (nth 3 foo))
and it stores in p the value stored at the index you want. You can also do
(setf (nth 3 foo) 444)
to store 444 at that place. But if you try to do something like
(setq pointer (nth 3 foo))
...
(setf pointer 444)
that won't work. In Emacs's trunk I have recently added gv-ref and gv-deref which would work just fine in such a case. They work pretty much like C's & and *:
(setq pointer (gv-ref (nth 3 foo)))
...
(setf (gv-deref pointer) 444)