Lisp: How to set element in list of lists? - lisp

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.

Related

CLISP representation of a list

I am experimenting with using substitute-if. Here I try to replace all values that are even in '((1) (2) (3) (4)) with '(0)
[9]> (substitute-if '(0) #'evenp '((1) (2) (3) (4)) :start 1 :key #'car)
((1) #1=(0) (3) #1#)
I am confused about the #1=(0) and #1 in the list. I expected it to return '((1) (0) (3) (0)).
Am I misunderstanding how substitute-if works or misunderstanding the representation of the list?
Am I misunderstanding how substitute-if works or misunderstanding the representation of the list?
Probably the latter.
#1=... marks a spot in the data structure and #1# refers back to it. The idea is to show that both elements refer to the same list. (See also http://www.lispworks.com/documentation/HyperSpec/Body/02_dhp.htm.)
It's like:
(let ((x '(0)))
(list '(1) x '(3) x))
Because they refer to the same object, if you were to modify the second list in place, the modification would also show up in the fourth list.
It seems like you have set the dynamic global variable *print-circle* to something truthy. If you evaluate *print-circle* you'll see it.
; make a list (1 1 1 1 1 ...)
(defparameter *test* (list 1))
(setf (cdr *test*) *test*)
(setf *print-circle* t)
(substitute-if '(0) #'evenp '((1) (2) (3) (4)) :start 1 :key #'car)
; ==> ((1) #1=(0) (3) #1#)
*test*
; ==> #1=(1 . #1#)
(setf *print-circle* nil)
(substitute-if '(0) #'evenp '((1) (2) (3) (4)) :start 1 :key #'car)
; ==> ((1) (0) (3) (0))
*test* ; never finishes
The last one will hang until it runs out of memory. be hurry to cancel it out or your system will surely be sluggish once it has used all your available memory and buffers and start getting the system to swap out other things.
This is why we have *print-circle*. The ability to see lists that are circular. The printed data structure is always the same so it's only how it is displayed which is different.
When you use substitute-if and replace with '(0) this has one address in memory and thus when *print-circle* is truthy it will only print it once and the other references will be shown as references since the system looks for the same object and not if it really is circular or not.

Scheme: vector function that returns the first odd number

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))

DELETE + SETF inside a function

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.

Define a syntax error in Lisp function

I am bad at Lisp. Help me please to find a syntax error. I need to write a function which swaps two elements in list. This function must consist loop-cycle. Here is what if have so far.
(defun swap-two-element(z x y)
(let ((newlist nil) (newlist2 nil) (copyz z) (copyz2 z) (newx nil))
(loop
(when (= (- (length z) (length copyz2)) y)
(return (set newx car z)))
(setq newlist2 (append newlist2(car copyz2))
copyz2 (cdr copyz2)))))
Call example: (swap-two-element '(a b c d) 2 3)
Replace the word set with the word values and you are good to go.
PS. You need to address the warnings though, and explain what the function is supposed to do so that we could help you with the algorithm.
You really need to tidy up your question. The title says nothing, the code is badly formatted and you really need to play around with loop to get started. I won't give you your solution since you need to learn this by trying. Here is an example you can make use of to do your assignment.
;; this orders a list by their odd index
;; NB: index starts at zero so first element is even
(defun order-odd-index (list)
(loop :for element :in list ; iterates your list
:for index :from 0 ; starts from 0 and goes on
:if (oddp index) ; if in a loop
:collect element :into odd-list ; variable is automatically created
:else ; else in a loop
:collect element :into even-list
:finally (return (append odd-list even-list)))) ; what to do in the end
(order-odd-index '(4 67 3 2 7 9)) ; ==> (67 2 9 4 3 7)
I use keywords (like :for instead of for) to indicate what symbols are loop keywords and what are not. It's optional but I think it looks a lot cleaner.
Now your problem can be solved with collecting element into 5 variables. Two of them is when index is equal to one of the places (given as arguments) to be switched the other 3 are before, in between and greater. In the finally you can just append those variables in the correct order and you're done.

Members in a list - LISP [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I need to write a program in Lisp to see the number of occurrences of a specific character in a list. For example the occurrences of 1 in the following list [1, 2, 3, 1,1]
A list in Lisp is a sequence of cons nodes: pairs of pointers - the first to the payload datum, and the second to the rest of the list. E.g. for [1,2,3,1,1],
.
/ \
1 .
/ \
2 .
/ \
3 ...... .
/ \
1 NIL
NIL is a special value signaling the empty list, such that the system knows not to try to explore it any further. In Scheme,
(define NIL '())
Recursive list processing paradigm is captured by the notion of fold, where each node . is "replaced" with a binary function f, and the special node NIL is replaced with some special "zero" value z, to create an application chain (f 1 (f 2 (f 3 (... (f 1 z) ...)))). In Scheme,
(define (myfold f z list)
(cond
((null? list) z) ; replace NIL with the initial ("zero") value
(else
(f ; combine
(car list) ; the payload datum, and the delayed,
(lambda () ; by creating a function to calculate it,
(myfold f z ; result of recursively folding
(cdr list))))))) ; the rest of list
That way, the combining function f must process two values: one is a node's payload datum, the other is the (delayed) result of recursively folding, with the same f and z, the rest of the list after that node.
(define (keep-equals v list)
(myfold
(lambda (a r) ; combine ...
(if (equal? v a)
(cons a ... ) ; the same thing goes over the dots, here
... )) ; and here
'() ; replace the NIL of the argument list with this
list))
Since the recursive folding results' calculation is delayed by creating a function to-be-called when the results are needed, we need to "force" that calculation to be performed, when we indeed need those results, by calling that function.
And if you want to count the number of occurrences instead of collecting them in a list, you just need to use a different combining function with a different initial ("zero") value.
In particular, we build a list by consing a value onto the rest of list (with NIL as the initial value, the empty list); whereas we count by incrementing a counter (with 0 as the initial value of that counter).
Calculating e.g. a list's length by folding, we essentially turn its elements each into 1: length [a,b,c,d,e] == 1 + (1 + (1 + (1 + (1 + 0)))). Here, the combining function will need to increment the counter conditionally, only when the payload data are such that we want to count them.
I like pretty well the answers already posted to this question. But it seems like they both involve a fair bit more than the necessary amount of work. On the other hand, given all the thought everyone's put into this, I'm almost embarrassed of how simple my answer is. Anyway, here's what I did:
(defun count-things-in (needle haystack)
"Count the number of NEEDLEs in HAYSTACK."
(reduce '+
(map 'list
#'(lambda (straw)
(if (equalp straw needle) 1 0))
haystack)))
(count-things-in 1 '(1 2 3 1 1))
;; => 3
It's pretty straightforward: you just map over HAYSTACK a function which returns 1 for an element which is EQUALP to NEEDLE or 0 for an element which isn't, and then reduce the resulting list by +. For the given example list, the map operation results in a list (1 0 0 1 1), which the reduce operation then treats as (1 + (0 + (0 + (1 + 1)))), which evaluates to 3.
Benefits of this approach include the use of an equality predicate loose enough to work with strings as well as numbers, and with numbers of different types but the same value -- that is, (equalp 1 1.0) => t; if you desire different behavior, use another equality predicate instead. Using the standard MAP and REDUCE functions, rather than implementing your own, also gives you the benefit of whatever optimizations your Lisp system may be able to apply.
Drawbacks include being not nearly as impressive as anyone else's implementation, and being probably not low-level enough to satisfy the requirements of the asker's homework problem -- not that that latter especially dismays me, given that this answer does satisfy the stated requirement.
I'm new to lisp myself but here is how I would do it. I haven't looked at the other answer yet from Will so I'll check that out after I post this. The member function has the utility of both telling you if it found something in a list, and also returning the rest of that list starting from where it found it:
CL-USER> (member '1 '(0 1 2 3))
(1 2 3)
You could then recursively call a function that uses member and increment a counter from returned values in a variable from a let:
(defun find1 (alist)
(let ((count 0))
(labels ((findit (list)
(let ((part (member '1 list)))
(if part
(progn (incf count)
(findit (rest part)))
0))
count))
(findit alist))))
Here is the result:
CL-USER> (find1 '(1 2 3 4 5))
1
CL-USER> (find1 '(1 1 2 3 4 5))
2
CL-USER> (find1 '(1 1 1 2 3 1 4 5 1 1))
6
You could get rid of that unattractive progn by using cond instead of if
UPDATE: Here is an updated and more elegant version of the above, based on the comments, that I think would qualify as tail recursive as well:
(defun find1 (alist &optional (accum 0))
(let ((part (member '1 alist)))
(if part
(find1 (rest part) (+ accum 1))
accum)))
Here it is in action:
CL-USER> (find1 '(1 2 3 4))
1
CL-USER> (find1 '(1 1 1 1))
4
CL-USER> (find1 '(1 1 0 1 1))
4
CL-USER> (find1 '(0 2 1 0 1 1 0 1 1))
5