How to use loops in LISP - list

I have been trying to understand how to use loops in LISP and they still don't really seem to work correctly. I tried using the following code:
(loop for i from 0 to (list-length y)
(when (eq (values-list (nth i (car y))) 0)
(return-from checkZero t)))
Which should loop through my list checking if my value is equal to 0 or not. If it is equal then it should return from and exit the loop, otherwise it should run until it reaches the list length. Am I thinking about this wrong and if so how do I go about fixing this loop?
(I'm not sure if my actual code works or not yet since I am still dealing with the errors generated by the incorrectly used loop and I can't find many good resources for using loops online)

The main problem in the loop is the WHEN-expression. There are two ways you can write that:
Use the loop WHEN condition DO forms-clause:
(loop for...
when (eq ...) do (return-from ...))
Use the regular WHEN-macro inside a loop DO-clause:
(loop for...
do (when (eq ...)
(return-from ...)))
There are a few other things to fix in your code.
When naming things in Lisp, use dashes between words rather than camelCase (check-zero rather than checkZero).
Use = for general numeric comparison, or ZEROP to check that a number is zero. EQ is used to check if two objects are the same object.
You can return from a loop using RETURN
I'm not quite sure what you're trying to accomplish with the (VALUES-LIST (NTH ... (CAR ...))), but it's not going to work. If you're trying to simply loop over a flat list of values (such as (1 2 3 4 5 6)), you should be using the loop FOR item IN list-clause.
So now you should have something like:
(defun check-zero (list)
(loop for item in list
when (zerop item) do (return t)))
LOOP also has a THEREIS condition-clause that you could use:
(defun check-zero (list)
(loop for item in list
thereis (zerop item)))
This return as soon as it finds an item that satisfies ZEROP. However, there are easier ways to achieve the same. You could use MEMBER to check if the list contains a zero:
(defun check-zero (list)
(member 0 list :test #'=))
CL-USER> (check-zero '(1 3 4 3 5 7))
NIL
CL-USER> (check-zero '(1 3 4 3 0 5 7))
(0 5 7)
This returns a generalized boolean. That is, any value that is not NIL is considered true in Common Lisp.
Since there is a predicate function (ZEROP) to check if an object is a zero, you could also use SOME or MEMBER-IF for this:
(some #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> T
(member-if #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> (0 45 6 7)

Related

In Racket how do i sum the alternating values in a list using recursion

I am writing a function using recursion that is supposed to add the alternating values in a list. It's relatively simple to just write some code to add all the values in the list but I am struggling to only add the alternating values in the list. If possible I would strongly prefer the code written using recursion over higher-order functions for this problem.
My only guess for this problem is to manipulate the length of the list to only add the alternating values of the list or to possibly find a way to only add the odd elements in the list but I have no clue if this is even possible and if it was even possible i would have no clue where to even begin.
This is my code so far
(define (skip-sum L)
(cond
[(empty? L) 0]
[else (+ (first L) (skip-sum (rest L)))]))
This is what the results should look like. As you can see only the odd elements in the lists were summed showing only alternating values in the list were added.
(check-expect (skip-sum (list 4 6 8)) 12)
(check-expect (skip-sum (list 1 3 5 7 9 11)) 15)
(check-expect (skip-sum (list 2 10 4 12 6 14 8 12 10))30)
For instance for the second example the alternating values which were added are 1+5+9=15.
Here is a possibile recursive definition:
(define (skip-sum l)
(cond ((empty? l) 0)
((empty? (cdr l)) (car l))
(else (+ (car l) (skip-sum (cddr l))))))
Note that there are two cases to end the recursion: when the list is empty, or has only one element.
In the recursive case we simply sum the first element of the list with the result of calling the function on the list starting from the third one (and so ignoring the second one). In this way we skip every even element and obtain the correct sum.

LISP How to remove element at certain index from a list

I'm trying to learn LISP. I got my way around functions and I wanted to test myself with some.
I was trying to write a function that can remove an element from a list in a given index.
This seems pretty straightforward, but I can't manage to do it.
Example: I have the list (20 8 13 10) and I want to remove the number at index 2.
How would I go about something like this?
It's very easy. This is the base case:
(remove-nth 0 '(2 3)) ; => (3)
And the default case:
(remove-nth 1 '(1 2 3)) ; ==
(cons 1 (remove-nth 0 '(2 3)))
The only thing left for you to do is to actually implement it!
There is a third case. What if the list is nil? In the strictest sense you cannot do the job and you should signal an error or perhaps there isn't anything to do so it's ok to then have it as a base case that evaluates to '() so that (remove-nth 5 '(1 2)) ; ==> (1 2)

Gathering elements in range of Min and Max values from a list in Scheme

I am new to Scheme and not currently using (Racket version), therefore I do not have such built in functions as filter and etc.
My task for now is to get elements out of my inputted list, and take out of it only those that are above my MinValue and below my MaxValue
In my "lst" variable for example I have (2 4 1 6 5 4 7 3)
In my "MinValue" I have 2
In my MaxValue I have 5
So that now after I apply something similar like
(remove (< # minVal) lst)
It technically should give remove and left out:
(2 4 4 3)
But I am getting the error:
READ from #<INPUT CONCATENATED-STREAM #<INPUT STRING-INPUT-STREAM> #<IO TERMINAL-STREAM>>: objects printed as # in view of *PRINT-LEVEL* cannot be read back in
Main questions:
Does Scheme has a specific defined variable like # that is iterating through the list when remove/remove-if functions are used, so I can use it?
Is there is a way to get this to work in such way:
(remove (< # minVal) lst)
Thanks!
tag "homework" should be there, but I cannot create it yet
Almost any Scheme I know of includes a filter procedure, it's not specific to Racket, you should be able to use it (remove is not the right tool for this job).
Simply pass a lambda that receives each element in turn and you can set any condition for determining which elements go in the output list:
(filter (lambda (e) (and (>= e 2) (< e 5)))
'(2 4 1 6 5 4 7 3))
=> '(2 4 4 3)
There is no # variable that iterates through a list and gives you each element in turn, to do that you have to explicitly traverse the list using recursion, or use one of the built-in procedures that expect a list and a lambda - the lambda's parameter represents each of the elements.
If for some reason you are not allowed to use filter, it's easy to implement it from scratch, and again notice that we don't need to use remove, and that pred gets called with each of the elements:
(define (filter pred lst)
(cond ((null? lst) '())
((pred (car lst))
(cons (car lst) (filter pred (cdr lst))))
(else (filter pred (cdr lst)))))

Appending Elements to an Existing List in Scheme

I need some help understanding the syntax on how to append a number into a list, i'm doing this from user input via the console so this elements have to be entered in recursively. So for ever number that is entered, the list must grow for each element (only numbers) added.
Here is the code I am working with, the problem lies in the second conditional. Right now this works but only creates an empty list of each number I put in, so the results would be
>12
>202
>30
()()()
zero input: stopping list
(define (inputlist)
(let ((applist list))
(let ((inpt (read)))
(cond
((= inpt 0)(newline) (display "zero input: stopping list"))
;;OLD((number? inpt) (cons inpt applist) (display (applist))(inputlist))
((number? inpt) (append (applist)(list inpt)) (display (applist))(inputlist))
(else
display "Not a number")))))
I understand why cons is not doing what I need it to be doing, but is there a similar functionality to appending each read in element to a pre-existing list?
EDIT: I've gotten closer what i've needed to do but still with the same results, i am now appending upon my applist with a list i create via every input, though it is still resulting in as many empty lists as I input.
SECOND EDIT: I've realized why it's printing multiple ()'s is because it's being called off the stack when 0 is entered, so i'm sure it's not working because the appending isn't working as intended, i've displayed the applist on the 0 conditional and it returns one null list.
A simple way to append an element to the end of a list while looping would be to do call append and update the reference to the list afterwards:
(set! applist (append applist (list inpt)))
Notice that you have several misplaced parentheses - in your code some are missing, some are unnecessary. In Scheme () means function application, and you have to be careful where you put those brackets.
Also, be aware that append doesn't modify the initial list, it creates a new one, and if you need to refer to it, you have to store it somewhere (that's why I'm doing a set! above).
There are more serious errors with you logic. The conditions are in the wrong order (you have to test if the input is a number before asking if it's zero), and you forgot to loop if something other than a number is entered. Also, if we pass along the list as a parameter to the loop, we won't have to do an ugly set!. Try this instead, it's closer to what you were aiming for:
(define (inputlist)
(let loop ((applist '()))
(let ((inpt (read)))
(cond ((not (number? inpt))
(display "not a number")
(newline)
(loop applist))
((zero? inpt)
(display "zero input: stopping list"))
(else
(let ((new-applist (append applist (list inpt))))
(display new-applist)
(newline)
(loop new-applist)))))))
As mentioned in the comments, bear in mind that appending at the end of a list inside a loop in general is a bad idea. It's ok for learning purposes, but in real-life code, you'd cons at the head of the list and reverse it at the end - this is more efficient.
Note that (cons x xs) where x is an element and xs is a list produces a new list which has x as its first element.
Here is one way to use cons to add an element in the end of a list:
Example:
Add 4 to (1 2 3)
1. Reverse the list: (3 2 1)
2. Add 4 to the front: (4 3 2 1)
3. Reverse: (1 2 3 4)
> (reverse (cons 4 (reverse (list 1 2 3)))
(1 2 3 4)
A function that uses this principle:
(define (cons-to-back x xs)
(reverse (cons x (reverse xs))))
> (cons-to-back 4 (list 1 2 3))
(1 2 3 4)
An alternative is to use append which appends the elements of two lists:
> (append '(1 2 3) '(4 5 6))
(1 2 3 4 5 6)
All we need to do, is to the the element into a list before using append:
> (append '(1 2 3) (list 4))
'(1 2 3 4)
Alternative definition of cons-to-back:
(define (cons-to-back x xs)
(append xs (list x)))

How does this Clojure form work? Removing a list from another list

I am doing a project for class and I stumbled upon some code that has proved useful, though I am not sure how the line below "reads". I understand the result of what it does, but not how it does it.
(remove #(some (partial = %) '(1 2 3 4)) '(1 2 3 5 6 7))
What it does is removes the values from the second set that are in the first if possible. So given two set P and V it finds P / V.
I guess I am looking for an English language sentence of what is happening?
Edit: Title. Also I do understand what remove does, given some predicate such as pos? it returns a lazy sequence of items that equate to true when the predicate is applied.
What I specifically do not understand is how #(some (partial = %)) evaluates to a predicate.
#(some (partial = %) '(1 2 3 4))
...is syntax sugar for...
(fn [x] (some (partial = x) '(1 2 3 4))
...so, calling
(#(some (partial = %) '(1 2 3 4)) 5)
...runs...
(some (partial = 5) '(1 2 3 4))
...thus, running (partial = 5) against every entry in '(1 2 3 4) until it finds a match -- thus: (= 5 1), (= 5 2), etc -- and returning nil when no match is returned.
nil is falsey. Thus, any sequence element for which no match exists will return false, and be retained by remove, whereas for anything with which a match exists, the predicate will return true and be removed.
Obviously, creating a lambda function for every item in one of your sequences and evaluating those functions against content of another sequence is extremely inefficient compared to real set arithmetic. Thus, this code shouldn't be used in any case where the number of items might be nontrivial.
Instead:
(clojure.set/difference
#{1 2 3 4 5 6 7}
#{1 2 3 4})
...would be the efficient and idiomatic approach. If you're starting with a list rather than a set literal, that might be replaced with (clojure.set/difference (into #{} list-a) (into #{} list-b)) or (clojure.set/difference (set list-a) (set list-b)).