Lisp loop do let when - lisp

I'm trying to do something like this
(loop for i from 1 to 10
do (let ((fi (funcall f i)))
when (> fi 0)
collect (list i fi)))
f is expensive to compute, so I want to only calculate it once.
This isn't working, so I introduce my fi local variable outside the loop scope:
(let ((fi nil))
(loop for i from 1 to 10
do (setf fi (funcall f i))
when (> fi 0)
collect (list i fi)))
Is there a way to do this (like the first way) that is completely contained within the loop macro?

Two independent for clauses will do:
(loop for i from 1 to 10
for fi = (funcall f i)
when (> fi 0)
collect (list i fi))
Both iteration clauses will be executed at every iteration. The second one will see each new value of i.

Related

Trying to return list of values at even positions in current list

The goal here is to pass a list to the function and have it return a list with the values at the even positions in that previous list.
eg. return-evens '(1 2 3) => (2) , return-evens '() => ()
I've finally created this function, however it is only working when I enter 0-3 values. And when I enter 0 or 1 values, instead of returning "()", it just returns "NIL".
How can I get this to work with more than 3 values, and how can I return it so that it prints it out as a list, with parentheses surrounding it?
(defun return-evens (lst)
(let ((return-list ()) (i 1))
(loop for x in lst
while (numberp x)
do (if (= (mod i 2) 0)
(setf return-list (append return-list x))
()
)
do (setq i (1+ i))
finally (return return-list))))
Some feedback to your code.
First big problem: it is not properly indented.
(defun return-evens (lst) ; in Lisp you can call it list instead of lst
; return is not a useful prefix.
; Every function returns something
(let ((return-list ()) (i 1)) ; LOOP can return lists and iterate.
; No need for this at all.
(loop for x in lst
while (numberp x) ; why this test? Are there non-numbers in the list?
do (if (= (mod i 2) 0) ; Lisp has a function EVENP
; but generally it is not necessary
(setf return-list (append return-list x))
; never append to the end. Never ever.
; Let LOOP collect a list, don't do it this way
()
)
do (setq i (1+ i)) ; iterating manually is not necessary
; that's what LOOP is for
finally (return return-list))))
; if you would let LOOP do the work, no RETURN necessary
A much simpler solution:
(defun elements-at-even-positions (list)
(loop for element in list
for even-position = nil then (not even-position)
when even-position collect element))

Looping through a list and appending to a new one

I'm new to Lisp. I'm trying to write a function that will take a list of dotted lists (representing the quantities of coins of a certain value), e.g.
((1 . 50) (2 . 20) (3 . 10)) ;; one 50 cent coin, two 20 cent coins, three 10 cent coins
and then convert it to list each coin by value, e.g.
(50 20 20 10 10 10)
Shouldn't be too hard, right? This is what I have so far. It returns NIL at the moment, though. Any ideas on fixing this?
(defun fold-out (coins)
(let ((coins-list (list)))
(dolist (x coins)
(let ((quantity (car x)) (amount (cdr x)))
(loop for y from 0 to quantity
do (cons amount coins-list))))
coins-list))
Since you can use loop, simply do
(defun fold-out (coins)
(loop
for (quantity . amount) in coins
nconc (make-list quantity :initial-element amount)))
alternatively, using dolist:
(defun fold-out (coins)
(let ((rcoins (reverse coins)) (res nil))
(dolist (c rcoins)
(let ((quantity (car c)) (amount (cdr c)))
(dotimes (j quantity) (push amount res))))
res))
If I were to do this, I'd probably use nested loops:
(defun fold-out (coins)
(loop for (count . value) in coins
append (loop repeat count
collect value)))
Saves a fair bit of typing, manual accumulating-into-things and is, on the whole, relatively readable. Could do with more docstring, and maybe some unit tests.
The expression (cons amount coins-list) returns a new list, but it doesn't modify coins-list; that's why the end result is NIL.
So you could change it to (setf coins-list (cons amount coins-list)) which will explicitly modify coins-list, and that will work.
However, in the Lisp way of doing things (functional programming), we try not to modify things like that. Instead, we make each expression return a value (a new object) which builds on the input values, and then pass that new object to another function. Often the function that the object gets passed to is the same function that does the passing; that's recursion.

Dr.racket Beginner Level function

I'm a beginner learner of dr.racket. I'm asked to write a function that does the following:
Write a function "readnum" that consumes nothing,and each time it is called, it will produce the Nth number of a defined list.
Example:
(define a (list 0 2 -5 0))
readnum --> 0 (first time readnum is called)
readnum --> 2 (second time readnum is called)
readnum --> -5 (third time readnum is called)
You dont have to worry about the case where the list does have numbers or no numbers left to be read.
Dr.racket is a functional language and it is very inconvinient to mutate variables and use them as counters, and in this problem I am not allowed to define other global functions and variables (local is allowed though).
Here is my attempt but it does not seems to work:
(define counter -1)
(define lstofnum (list 5 10 15 20 32 3 2))
(define (read-num)
((begin(set! counter (+ 1 counter)))
(list-ref lstofnum counter)))
Not only I defined global variable which is not allowed, the output is not quite right either.
Any help would be appreciated, thanks!
The trick here is to declare a local variable before actually defining the function, in this way the state will be inside a closure and we can update it as we see fit.
We can implement a solution using list-ref and saving the current index, but it's not recommended. It'd be better to store the list and cdr over it until its end is reached, this is what I mean:
(define lstofnum (list 0 2 -5 0))
(define readnum
(let ((lst lstofnum)) ; list defined outside will be hardcoded
(lambda () ; define no-args function
(if (null? lst) ; not required by problem, but still...
#f ; return #f when the list is finished
(let ((current (car lst))) ; save the current element
(set! lst (cdr lst)) ; update list
current))))) ; return current element
It works as expected:
(readnum)
=> 0
(readnum)
=> 2
(readnum)
=> -5
(readnum)
=> 0
(readnum)
=> #f

A lisp function refinement

I've done the Graham Common Lisp Chapter 5 Exercise 5, which requires a function that takes an object X and a vector V, and returns a list of all the objects that immediately precede X in V.
It works like:
> (preceders #\a "abracadabra")
(#\c #\d #r)
I have done the recursive version:
(defun preceders (obj vec &optional (result nil) &key (startt 0))
(let ((l (length vec)))
(cond ((null (position obj vec :start startt :end l)) result)
((= (position obj vec :start startt :end l) 0)
(preceders obj vec result
:startt (1+ (position obj vec :start startt :end l))))
((> (position obj vec :start startt :end l) 0)
(cons (elt vec (1- (position obj vec :start startt :end l)))
(preceders obj vec result
:startt (1+ (position obj vec
:start startt
:end l))))))))
It works correctly, but my teachers gives me the following critique:
"This calls length repeatedly. Not so bad with vectors, but still unnecessary. More efficient and more flexible (for the user) code is to define this like other sequence processing functions. Use :start and :end keyword parameters, the way the other sequence functions do, with the same default initial values. length should need to be called at most once."
I am consulting the Common Lisp textbook and google, but there seem to be of little help on this bit: I don't know what he means by "using :start and :end keyword parameters", and I have no clue of how to "call length just once". I would be grateful if you guys could give me some idea how on to refine my code to meet the requirement that my teacher posted.
UPDATE:
Now I have come up with the following code:
(defun preceders (obj vec
&optional (result nil)
&key (start 0) (end (length vec)) (test #'eql))
(let ((pos (position obj vec :start start :end end :test test)))
(cond ((null pos) result)
((zerop pos) (preceders obj vec result
:start (1+ pos) :end end :test test))
(t (preceders obj vec (cons (elt vec (1- pos)) result)
:start (1+ pos) :end end :test test)))))
I get this critique:
"When you have a complex recursive call that is repeated identically in more than one branch, it's often simpler to do the call first, save it in a local variable, and then use the variable in a much simpler IF or COND."
Also,for my iterative version of the function:
(defun preceders (obj vec)
(do ((i 0 (1+ i))
(r nil (if (and (eql (aref vec i) obj)
(> i 0))
(cons (aref vec (1- i)) r)
r)))
((eql i (length vec)) (reverse r))))
I get the critique
"Start the DO at a better point and remove the repeated > 0 test"
a typical parameter list for such a function would be:
(defun preceders (item vector
&key (start 0) (end (length vector))
(test #'eql))
...
)
As you can see it has START and END parameters.
TEST is the default comparision function. Use (funcall test item (aref vector i)).
Often there is also a KEY parameter...
LENGTH is called repeatedly for every recursive call of PRECEDERS.
I would do the non-recursive version and move two indexes over the vector: one for the first item and one for the next item. Whenever the next item is EQL to the item you are looking for, then push the first item on to a result list (if it is not member there).
For the recursive version, I would write a second function that gets called by PRECEDERS, which takes two index variables starting with 0 and 1, and use that. I would not call POSITION. Usually this function is a local function via LABELS inside PRECEDERS, but to make it a bit easier to write, the helper function can be outside, too.
(defun preceders (item vector
&key (start 0) (end (length vector))
(test #'eql))
(preceders-aux item vector start end test start (1+ start) nil))
(defun preceders-aux (item vector start end test pos0 pos1 result)
(if (>= pos1 end)
result
...
))
Does that help?
Here is the iterative version using LOOP:
(defun preceders (item vector
&key (start 0) (end (length vector))
(test #'eql))
(let ((result nil))
(loop for i from (1+ start) below end
when (funcall test item (aref vector i))
do (pushnew (aref vector (1- i)) result))
(nreverse result)))
Since you already have a solution that's working, I'll amplifiy Rainer Joswig's solution, mainly to make related stylistic comments.
(defun preceders (obj seq &key (start 0) (end (length seq)) (test #'eql))
(%preceders obj seq nil start end test))
The main reason to have separate helper function (which I call %PRECEDERS, a common convention for indicating that a function is "private") is to eliminate the optional argument for the result. Using optional arguments that way in general is fine, but optional and keyword arguments play horribly together, and having both in a single function is a extremely efficient way to create all sorts of hard to debug errors.
It's a matter of taste whether to make the helper function global (using DEFUN) or local (using LABELS). I prefer making it global since it means less indentation and easier interactive debugging. YMMV.
A possible implementation of the helper function is:
(defun %preceders (obj seq result start end test)
(let ((pos (position obj seq :start start :end end :test test)))
;; Use a local binding for POS, to make it clear that you want the
;; same thing every time, and to cache the result of a potentially
;; expensive operation.
(cond ((null pos) (delete-duplicates (nreverse result) :test test))
((zerop pos) (%preceders obj seq result (1+ pos) end test))
;; I like ZEROP better than (= 0 ...). YMMV.
(t (%preceders obj seq
(cons (elt seq (1- pos)) result)
;; The other little bit of work to make things
;; tail-recursive.
(1+ pos) end test)))))
Also, after all that, I think I should point out that I also agree with Rainer's advice to do this with an explicit loop instead of recursion, provided that doing it recursively isn't part of the exercise.
EDIT: I switched to the more common "%" convention for the helper function. Usually whatever convention you use just augments the fact that you only explicitly export the functions that make up your public interface, but some standard functions and macros use a trailing "*" to indicate variant functionality.
I changed things to delete duplicated preceders using the standard DELETE-DUPLICATES function. This has the potential to be much (i.e., exponentially) faster than repeated uses of ADJOIN or PUSHNEW, since it can use a hashed set representation internally, at least for common test functions like EQ, EQL and EQUAL.
A slightly modofied variant of Rainer's loop version:
(defun preceders (item vector
&key (start 0) (end (length vector))
(test #'eql))
(delete-duplicates
(loop
for index from (1+ start) below end
for element = (aref vector index)
and previous-element = (aref vector (1- index)) then element
when (funcall test item element)
collect previous-element)))
This makes more use of the loop directives, and among other things only accesses each element in the vector once (we keep the previous element in the previous-element variable).
Answer for your first UPDATE.
first question:
see this
(if (foo)
(bar (+ 1 baz))
(bar baz))
That's the same as:
(bar (if (foo)
(+ 1 baz)
baz))
or:
(let ((newbaz (if (foo)
(+ 1 baz)
baz)))
(bar newbaz))
Second:
Why not start with I = 1 ?
See also the iterative version in my other answer...
The iterative version proposed by Rainer is very nice, it's compact and more efficient since you traverse the sequence only one time; in contrast to the recursive version which calls position at every iteration and thus traverse the sub-sequence every time. (Edit: I'm sorry, I was completely wrong about this last sentence, see Rainer's comment)
If a recursive version is needed, another approach is to advance the start until it meets the end, collecting the result along its way.
(defun precede (obj vec &key (start 0) (end (length vec)) (test #'eql))
(if (or (null vec) (< end 2)) nil
(%precede-recur obj vec start end test '())))
(defun %precede-recur (obj vec start end test result)
(let ((next (1+ start)))
(if (= next end) (nreverse result)
(let ((newresult (if (funcall test obj (aref vec next))
(adjoin (aref vec start) result)
result)))
(%precede-recur obj vec next end test newresult)))))
Of course this is just another way of expressing the loop version.
test:
[49]> (precede #\a "abracadabra")
(#\r #\c #\d)
[50]> (precede #\a "this is a long sentence that contains more characters")
(#\Space #\h #\t #\r)
[51]> (precede #\s "this is a long sentence that contains more characters")
(#\i #\Space #\n #\r)
Also, I'm interested Robert, did your teacher say why he doesn't like using adjoin or pushnew in a recursive algorithm?

Is it correct to use the backtick / comma idiom inside a (loop ...)?

I have some code which collects points (consed integers) from a loop which looks something like this:
(loop
for x from 1 to 100
for y from 100 downto 1
collect `(,x . ,y))
My question is, is it correct to use `(,x . ,y) in this situation?
Edit: This sample is not about generating a table of 100x100 items, the code here just illustrate the use of two loop variables and the consing of their values. I have edited the loop to make this clear. The actual loop I use depends on several other functions (and is part of one itself) so it made more sense to replace the calls with literal integers and to pull the loop out of the function.
It would be much 'better' to just do (cons x y).
But to answer the question, there is nothing wrong with doing that :) (except making it a tad slower).
I think the answer here is resource utilization (following from This post)
for example in clisp:
[1]> (time
(progn
(loop
for x from 1 to 100000
for y from 1 to 100000 do
collect (cons x y))
()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
CL.
Real time: 0.469 sec.
Run time: 0.468 sec.
Space: 1609084 Bytes
GC: 1, GC time: 0.015 sec.
NIL
[2]> (time
(progn
(loop
for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y)) ;`
()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
CL.
Real time: 0.969 sec.
Run time: 0.969 sec.
Space: 10409084 Bytes
GC: 15, GC time: 0.172 sec.
NIL
[3]>
dsm: there are a couple of odd things about your code here. Note that
(loop for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y))
is equivalent to:
(loop for x from 1 to 100
collecting (cons x x))
which probably isn't quite what you intended. Note three things: First, the way you've written it, x and y have the same role. You probably meant to nest loops. Second, your do after the y is incorrect, as there is not lisp form following it. Thirdly, you're right that you could use the backtick approach here but it makes your code harder to read and not idiomatic for no gain, so best avoided.
Guessing at what you actually intended, you might do something like this (using loop):
(loop for x from 1 to 100 appending
(loop for y from 1 to 100 collecting (cons x y)))
If you don't like the loop macro (like Kyle), you can use another iteration construct like
(let ((list nil))
(dotimes (n 100) ;; 0 based count, you will have to add 1 to get 1 .. 100
(dotimes (m 100)
(push (cons n m) list)))
(nreverse list))
If you find yourself doing this sort of thing a lot, you should probably write a more general function for crossing lists, then pass it these lists of integers
If you really have a problem with iteration, not just loop, you can do this sort of thing recursively (but note, this isn't scheme, your implementation may not guaranteed TCO). The function "genint" shown by Kyle here is a variant of a common (but not standard) function iota. However, appending to the list is a bad idea. An equivalent implementation like this:
(defun iota (n &optional (start 0))
(let ((end (+ n start)))
(labels ((next (n)
(when (< n end)
(cons n (next (1+ n))))))
(next start))))
should be much more efficient, but still is not a tail call. Note I've set this up for the more usual 0-based, but given you an optional parameter to start at 1 or any other integer. Of course the above can be written something like:
(defun iota (n &optional (start 0))
(loop repeat n
for i from start collecting i))
Which has the advantage of not blowing the stack for large arguments. If your implementation supports tail call elimination, you can also avoid the recursion running out of place by doing something like this:
(defun iota (n &optional (start 0))
(labels ((next (i list)
(if (>= i (+ n start))
nil
(next (1+ i) (cons i list)))))
(next start nil)))
Hope that helps!
Why not just
(cons x y)
By the way, I tried to run your code in CLISP and it didn't work as expected. Since I'm not a big fan of the loop macro here's how you might accomplish the same thing recursively:
(defun genint (stop)
(if (= stop 1) '(1)
(append (genint (- stop 1)) (list stop))))
(defun genpairs (x y)
(let ((row (mapcar #'(lambda (y)
(cons x y))
(genint y))))
(if (= x 0) row
(append (genpairs (- x 1) y)
row))))
(genpairs 100 100)