Mutiple value bind in do loop in Common Lisp - common-lisp

How do you bind multiple values returned from a function, inside a do loop?
The following is obviously very wrong, but is something like this possible?
(do (((x y z) (3-val-fn) (3-val-fn)))
((equal y 'some-val) y)
(values x y z))
Or maybe there is a way to do this using multiple-value-bind?

Multiple values in the standard iteration constructs is not really supported.
With LOOP your snippet might look like this:
(loop with x and y and z
do (setf (values x y z) (3-val-fn))
while (equal y 'some-val)
finally (return y)
do ...)
If I would need something like that often, I might define a do-mv macro which would expand into above code. Code then would look like:
(do-mv ((x y z) (3-val-fn))
((equal y 'some-val) y)
...)
The advantage to use above is that it does not create lists from multiple values during each iteration. Creating lists out of multiple values kind of defeats the purpose of multiple values, which are there to return more than one values and allowing it to be implemented in an efficient way.

How about?:
(loop for (x y z) = (multiple-value-list (3-val-fn))
...etc)
I'd offer more but cannot understand the do-loop.

It's (sort-of) doable with do*:
(defun foo (n)
(do* ((n n (1- n))
(values (multiple-value-list (truncate 17 n))
(multiple-value-list (truncate 17 n)))
(result (first values) (first values))
(remainder (second values) (second values)))
((< n 3) nil)
(format t "Result: ~d, remainder: ~d, n: ~d~%" result remainder n)))
Here we first convert the multi-valued function result into a list, bind that to a variable and then manually destructure it. But it is hard to read and should probably be avoided, unless the do family of iteration constructs really happens to be a lot better choice than using loop.

Related

Check the type of an argument without using COND, IF, WHEN, UNLESS, or CASE

I have this function that is working fine when the inputs are number: it returns T if both inputs have the same sign, NIL otherwise. However, when I give for example two 'a, I get this error:
a is not a real number
I'm finding it tricky to filer non numbers without using COND, IF, WHEN, UNLESS, or CASE. Here is the function definition I have so far.
(defun same-sign (x y)
(or (and (>= x 0) (>= y 0))
(and (< x 0) (< y 0))))
You can use check-type:
(defun same-sign (x y)
(check-type real x)
(check-type real y)
(= (signum x) (signum y)))
Since signum can also work with complex numbers, you could use number instead of real here, if it makes sense for your application.
Signum treats 0 separately, though, so you might use minusp instead (wrapping to potentially un-generalize the boolean):
(defun binary-sign (n)
"Returns -1 if n is negative, 1 otherwise."
(check-type real n)
(if (minusp n) -1 1))
(defun same-sign-p (x y)
"Returns whether both given real numbers are either both negative or both
non-negative."
(= (binary-sign x) (binary-sign y)))
As you see, you can avoid writing two checks by putting the check into the more detailed function. However, you can imagine that minusp already has such a check, so you can be reasonably sure that an appropriate type-error will be signalled anyway if you don't call this with reals.
You might mean type real and not number. Type number consists of real (integers and floats) and complex (2 real components) values. An example of a complex number is #C(1 2) = 1 + 2i
Try (and (realp x) ...) to filter real numbers, equivalent to (and (typep x 'real) ...).
Also (typecase x (real ..)) or using a generic function and (defmethod foo ((x real)) ..) work, except you seem to want to restrict yourself to basic logical operators.
(defun same-sign (x y)
(and (typep x 'real) (typep y 'real)
(or (and (>= x 0) (>= y 0))
(and (< x 0) (< y 0)))))

What does the following function do in Scheme programming language

(define (unknown (lambda (x y)
(cond
((null? y) y)
((x (car y)) (unknown x (cdr y))))
(else (cons (car y) (unknown x (cdr y)))))))
I'm a newbie when it comes to scheme and wanted to know the purpose of this function which I came across in a textbook. My main doubt lies as to what ((x (car y)) does. How does this expression get executed without any operators and yet I don't come across any errors while compiling. Although I'm unable to run the program because the values I input for x are apparently not applicable for the function. Please help.
Scheme functions can take functions as arguments, and can return functions. Your code makes sense if you pass in a function as an argument.
If you call the code like this:
(unknown even? '(1 2 3 4 5))
then it should return the list (1 3 5). This is a filtering function that returns members of y where the result of applying the function x to the member is false.

Types of recursion in Sceme

I'm studying Scheme language (by myself). Recently I've encountered this question:
There are two functions which compute the same value (compose function f - n times).
(define (repeated f n)
(lambda (x)
(if (= n 1)
(f x)
(f ((repeated f (- n 1)) x)))))
(define (repeated f n)
(if (= n 1)
f
(lambda (x)
(f ((repeated f (- n 1)) x)))))
As I understood these two are not recursive procedures but they return recursive procedures (lol). So what is the difference between these two? Is it possible that the first returns already computed procedure even before I give value to X? I'm so confused... Please help.
In fact both procedures are recursive, each one is calling itself at some point during the execution. Also, both are returning a lambda at some point - meaning: they're procedures that return procedures.
The first procedure always returns a lambda, whereas the second procedure short-circuits and returns f when n equals 1, but also returns a lambda for values of n greater than 1. So they're not different, except for the way the base case (n equals 1) is handled.
Wow that's so much simpler than mine, though mine is tail-recursive and works for (repeated fn 0) asuuming that running a function zero times on an argument is just that argument.
(define (repeated fn times)
(let loop (
(continuation (lambda (x) x))
(count-down times))
(if (not (> count-down 0))
(lambda (x) (continuation x))
(loop (lambda (x) (continuation (fn x))) (- count-down 1)))))
The difference between the two of yours is that the first returns a procedure right-away, and then calls itself as part of the procedure. The second returns a procedure only after it's fully calculated what that procedure will be.
Right so the first returns a recursive procedure, while the second used recursion to return a non-recursive procedure. Mine works more like the second, but can calculate repitition for very large numeric values while the two above will exceed the maximum recursion depth.
((repeated cdr 1000000) (iota 1000589))

towers of hanoi in common lisp

I think this is going to be a vague question because I don't know exactly what I am doing in the first place but here it goes.
I have to do a towers of hanoi problem in common lisp using lists. Basically a function takes a list of strings (names) and then moves them from peg A to peg C using peg B for storage, keeping them in the same order as they were in the list.
I have never used lisp before and I find the syntax very hard to understand.
This is my code so far
goo function is the hanoi work
(defparameter A '())
(defparameter B '())
(defparameter C '())
(defun findPeg (p1 p2) (cond ((= 0 (- 3 p1 p2))A)
((= 1 (- 3 p1 p2))B) ((= 2 (- 3 p1 p2))C)))
(defun getnum (x) (cond ((equalp x A) 0)((equalp x B)1)((equalp x C) 2)))
(defun hanoi (x) (defparameter A x) (setlength A)(goo len A C B))
(defun setlength(x) (defparameter len (list-length x)))
(defun goo (leng from to via)
(cond ((= leng 1)(push (pop A) C)) ;base case
((goo (1- leng) from via to)(push (pop A) B) ;say/do something i think
((goo (1- leng) via to from)(push (pop B) C) ;say/do something i think
))))
My problem is with the recursive calls. I am very confused as to what exactly I should be doing. I know I obviously have to move the first string in the first list to another peg, but I don't know which peg or even how to manipulate the lists. I feel like I should be using the variables that were passed into the goo function, but I cant figure out how to edit them because when I change them in the function the variables outside do not change.
Right now I am running into the error
* - SYSTEM::%EXPAND-FORM: (GOO (1- LENG) FROM VIA TO) should be a lambda expression
This is a recursive call so I don't know why it is saying that.
Basically I just want some tips or tricks on where do continue or ever where to restart because I don't even know if my approach is a good one.
Anything is greatly appreciated. Thanks
First off, using defparameter inside a DEFUN is almost never the right thing to do.
If you want to have a lexically-scoped variable, use LET (or simply name your formal parameters as you'd like them named).
Second, you have something on the form ((fun arg ..) (fun arg ...)) inside your GOO function. You want to lose the outermost parentheses.

Flatten a list two ways: (i) using MAPCAN and (ii) using LOOP

My professor has given us a refresher assignment in clisp. One exercise is to achieve the same thing in three ways: Return a flattened list of all positive integers in a given list.
Now, there's only one way I really like doing this, using cons and recursion, but he wants me to do this using mapcan and a loop (I suspect lisp is not his first choice of language because this style of coding feels extremely resistant to the nature of lisp). I'm having a hard time working out how one would do this using a loop...I need to first start a list, I suppose?
I apologize for vague language as I'm not really sure how to TALK about using a functional language to write procedurally. Following is my first attempt.
(defun posint-loop (l)
(loop for i in l
do (if (listp i)
(posint-loop i)
(if (integerp i)
(if (> i 0)
(append i) ; this doesn't work because there's nothing to
; start appending to!
nil)
nil))))
In order to establish a new lexical binding, use let or the with keyword of loop. In order to extend an existing list, you might want to use push; if you need the original order, you can nreverse the new list finally.
Another way would be to use the when and collect keywords of loop.
Another hint: mapcan implicitly creates a new list.
Mapcan applies a function to each element of a list, expecting the function to return a list, and then concatenates those resulting lists together. To apply it to this problem, you just need to process each element of the toplevel list. If the element is a list, then you need to process it recursively. If it's not, then you either need to return an empty list (which will add no elements to the final result) or a list of just that element (which will add just that element to the final result):
(defun flatten2 (list)
(mapcan (lambda (x)
(cond
((listp x) (flatten2 x))
((and (integerp x) (plusp x)) (list x))
(t '())))
list))
(flatten2 '((a 1 -4) (3 5 c) 42 0))
;=> (1 3 5 42)
With loop, you can do just about the same thing with the recognition that (mapcan f list) is functionally equivalent to (loop for x in list nconc (funcall f x)). With that in mind, we have:
(defun flatten3 (list)
(loop for x in list
nconc (cond
((listp x) (flatten3 x))
((and (integerp x) (plusp x)) (list x))
(t '()))))

Resources