why does this do times lisp loop giving me issues? - loops

Am trying to implement the function element I that return the i-th element of the list.car of the list is element 0,1 etc and I'm trying to use the dotimes loop together with the pop function and I keep getting errors
(defun element-i (y L)
;; (setq m )
(let ((m ( cdr L));;(return car L))
(dotimes(m (cdr L) t)
(if (equal y 0) (return car L)
(pop car L)
(setq i (+ m L)))))))

You have a number of issues here. First, you are using a parameter y but inside the function you call it i. Further L is a list, so (+ m L) will signal an error. On the other hand, I think you intend to use m as an integer, but you initialize it as (cdr L) which is a list.
Also, the function pop modifies the list L, but it's much easier to use a variable to point at the next element of the list, without modifying the list, simply by saying (setq m (cdr m)).
You can rewrite the function in a simpler way, thinking along these lines: take a variable m and initialize it to L. Loop i times through the list, making each time m equal to (cdr m), i.e. the same list minus the first element of the previous loop. Once you exit the loop m will be the sublist whose car is the i-th element of L.

Related

Unused loop variables in Lisp

Sometime, I need to iterate $n$ times where $n$ is the number of elements in a list. Of course, I could write something like:
(loop for i from 0 below (list-length l)
do something)
But I like to write rather:
(loop for i from 0
for u in l ; unused 'u' variable
do something)
where the for u in l part is merely intended to stop the loop after $n$ iterations. But then I don't use the u variable, and the interpreter keeps complaining. Is there some way to handle this style of coding? Should I avoid it and use list-length instead?
(loop for i from 0
for NIL in l
do something)
NIL should do it.
The LOOP destructuring pattern can be empty and the rest list elements are ignored.
Additionally: In a LOOP destructuring pattern, NIL indicates that the variable is not used.
Try the repeat clause:
(loop repeat (length l) ...)
The argument expression of the repeat clause is required to be evaluated once.
One horrible hack to do this which does not involve any extra traversals and if you really need to use loop is:
(defun foo (l)
(loop for i upfrom 0
for u = l then (cdr u)
while (consp u)
collect i))
But probably Kaz's answer of (loop repeat (length l) ...) is fine in practice, if you must use loop.

Making a recursive call from the loop macro

I'm pretty new to common lisp and I've been stuck on a particular problem. The function I'm suppose to write takes in two parameters: a function and a List. It iterates through the list and calls the given function on each element in the list. If the function returns true then the element is added to a sub list that is returned
What I've tried so far is:
(defun myFunc(f l)
(loop for x in l
if (listp x) do (myFunc f x)
else if (eql t (funcall f x))
collect x
)
)
The function I've been given for f takes a parameter and if it's is an number, returns true. So far my code works if aList is a simple list such as (1 2 3). However when I input a nested list like (1 2 (4 5) 7) only (1 2 7) is outputted rather than (1 2 (4 5) 7).
I'm assuming it has something to do with my recursive call and what is returning. Would really appreciate some help on this
There are a couple of minor issues. First off, I assume it's just a typo, but you need to replace aFunc with f (as there's no variable aFunc in your code).
Now to the main point of the question. In your else if branch, you correctly collect the value when the predicate is true. But in your recursive case, you simply run some code and discard the result. You're going to want to collect there too.
(defun myFunc (f l)
(loop for x in l
if (listp x)
collect (myFunc f x)
else if (eql t (funcall f x))
collect x))
Finally, just a style note. It's generally more idiomatic to treat a predicate as true if it returns anything truthy, not just t. So if I was writing this, I'd probably replace (eql t (funcall f x)) with simply (funcall f x). If this is a homework assignment and the teacher told you to do it the other way, stick with that. But if it's for your benefit, you may consider changing that as well.

Lisp Loop Largest Number

I've been fiddling with Lisp programs for a little while and one thing that I can never seem to figure out is how to use a loop on a list inside a function. I'm trying to create a function that will take a list as the parameters while using a do... loop. I know how to do it with if statements but now I need to use a loop. Does anyone have a clue on how to do that?
(defun maximum (a_list)
(if (= (length a_list) 1)
(car a_list)
(if (> (car a_list) (maximum (cdr a_list)))
(car a_list)
(maximum (cdr a_list))))
(format t "~d" a_list))
Here's what I have so far on the if statements. They might not work right but at least they work.
Here another set of possibilities, in addition to those proposed in another answers.
First of all, when writing a function, one should also test for special cases, while you do not check for an empty list. So the structure of the function could be something of this type:
(defun maximum (l)
(if (null l)
nil ; or give an error
...normal solution...))
In case of returning nil, this structure in Common Lisp is identical to the following one, given that and evaluates its arguments in sequence, and returns nil as soon as an argument is evaluated to nil, otherwise returns the value of the last argument:
(defun maximum (l)
(and l ...normal solution...))
Here the alternative solutions.
Without loop or recursion, with predefined functions reduce (manual) and max (manual).
(defun maximum (l)
(and l (reduce #'max l)))
With the construct dolist (manual), that iterates a variable over a list:
(defun maximum (l)
(and l (let ((result (car l)))
(dolist (x (cdr l) result)
(when (> x result)
(setf result x))))))
And finally, with a compact version of do (manual):
(defun maximum (l)
(and l (do ((maximum-so-far (car l) (max (pop l) maximum-so-far)))
((null l) maximum-so-far))))
With loop the solution is trivial:
(loop for x in '(1 2 7 4 5) maximize x)
I assume therefore that what you intend to do is to write the function with a do loop. In this case you have to traverse the list keeping track of the maximum element so far, and updating this value if you find a larger value:
(setq list '(1 2 7 4 5))
(do* ((l list (cdr l))
(x (car l) (car l))
(max x) )
((null l) max)
(if (> x max)
(setq max x) ))
(defun maximum (list)
(let ((result)) ;; short for ((result nil))
(dolist (x list)
(if result
(when (> x result)
(setf result x))
(setf result x)))
result))
(dolist (x list) ... ) is like Python's [... for x in list]
It is typical imperative style to create a variable with
let and setf to it to change its value.

Conditionals in Elisp's cl-loop facility

I'm trying to wrap my head around Elisp's cl-loop facility but can't seem to find a way to skip elements. Here's an artificial example to illustrate the problem: I'd like to loop over a list of integers and get a new list in which all odd integers from the original list are squared. The even integers should be omitted.
According to the documentation of cl-loop, I should be able to do this:
(loop for i in '(1 2 3)
if (evenp i)
append (list)
else
for x = (* x x)
and append (list x))
The desired output is '(1 9) instead I get an error:
cl--parse-loop-clause: Expected a `for' preposition, found (list x)
Apparently the and doesn't work as expected but I don't understand why. (I'm aware that I could simplify the else block to consist of only one clause such that the and isn't needed anymore. However, I'm interested in situations where you really have to connect several clauses with and.)
Second part of the question: Ideally, I would be able to write this:
(loop for i in '(1 2 3)
if (evenp i)
continue
for x = (* x x)
append (list x))
Continue is a very common way to skip iterations in other languages. Why doesn't cl-loop have a continue operator? Is there a simple way to skip elements that I overlooked (simpler than what I tried in the first example)?
In Common Lisp it is not possible to write such a LOOP. See the LOOP Syntax.
There is a set of variable clauses on the top. But you can't use one like FOR later in the main clause. So in an IF clause you can't use FOR. If you want to introduce a local variable, then you need to introduce it at the top as a WITH clause and set it later in the body.
(loop for i in '(1 2 3)
with x
if (evenp i)
append (list)
else
do (setf x (* i i))
and append (list x))
LOOP in Common Lisp also has no continue feature. One would use a conditional clause.
Note, that Common Lisp has a more advanced iteration construct as a library ITERATE. It does not exist for Emacs Lisp, though.
You could do:
(loop for i in '(1 2 3)
if (oddp i) collect (* i i))
That would solve your sample problem.
And here's another without loop (yes, I know you asked for loop):
(let ((ns ()))
(dolist (n '(1 2 3))
(when (oddp n) (push (* n n) ns)))
(nreverse ns))
And without even cl-lib (which defines oddp):
(let ((ns ()))
(dolist (n '(1 2 3))
(unless (zerop (mod n 2)) (push (* n n) ns)))
(nreverse ns))
Everything about such definitions is clear -- just Lisp. Same with #abo-abo's examples.
loop is a separate language. Its purpose is to express common iteration scenarios, and for that it can do a good job. But Lisp it is not. ;-) It is a domain-specific language for expressing iteration. And it lets you make use of Lisp sexps, fortunately.
(Think of the Unix find command -- similar. It's very handy, but it's another language unto itself.)
[No flames, please. Yes, I know that dolist and all the rest are essentially no different from loop -- neither more nor less Lisp. But they are lispier than loop. Almost anything is lispier than loop.]
Here's a loop solution:
(loop for i in '(1 2 3)
when (oddp i) collect (* i i))
Here's a functional solution:
(delq nil
(mapcar (lambda(x) (and (oddp x) (* x x)))
'(1 2 3)))
Here's a slightly different solution (be careful with mapcan - it's destructive):
(mapcan (lambda(x) (and (oddp x) (list (* x x))))
'(1 2 3))

Scheme while loop

I'm kinda new in scheme syntax... I'm trying to make a simple program where you input an integer, if the integer is even do something and if it's odd do something else.
I was able to do this part. Now, I need to make a loop where I can decrement the number until it equals to 1.
Here is my code :
#lang racket
(define (even? n)
(if (eqv? n 0) #t
(odd? (- n 1))))
(define (odd? n)
(if (eqv? n 0) #f
(even? (- n 1))))
; this is the function that i wanted to be inside the loop
(define (sequence n)
(cond
[(even? n) n( / n 2)]
[(odd? n) n(+(* n 3) 1) ] )
)
(sequence 5)
The output should be a sequence of numbers. In other words, it should be inside a list.
An output list is built by consing each of the elements that are part of the list and then advancing the recursion over the input, until the input is exhausted (in your case, when the number n is one). By successively consing elements at the head of the list and ending the recursion with a null value, a new proper list is created and returned at the end of the procedure execution. Here's how:
(define (sequence n)
(cond [(= n 1) ; if n=1, it's the exit condition
(list n)] ; return a list with last element
[(even? n) ; if n is even
(cons n (sequence (/ n 2)))] ; cons n and advance the recursion
[(odd? n) ; if n is odd
(cons n (sequence (+ (* n 3) 1)))])) ; cons n and advance the recursion
The above will return a list with the Collatz sequence for the given number n:
(sequence 6)
=> '(6 3 10 5 16 8 4 2 1)
As a side note: the procedures even? and odd? are standard in Scheme and you don't have to redefine them.

Resources