Quicksort, problem with understanding Common Lisp code - functional-programming

for my study I need to explain the function of Quicksort programmed in Common Lisp. I am honest, I really don't know how to work with Common Lisp. I got a code from the internet (for my professer it is okay to use the code from the internet) which solves the problem of sorting a list of numbers.
I really don't understand this code, can somebody please explain it to me, what it exacly does?
Thanks so far!!
(defun quick-sort (list)
(if (cdr list)
(let ((pivot (car list)))
(flet ((filter (operator)
(remove-if-not
(lambda (n) (funcall operator n pivot))
list)))
(append (quick-sort (filter #'<))
(filter #'=)
(quick-sort (filter #'>)))))
list))

Related

Reverse a list in scheme

I'm trying to reverse a list in scheme and I came up with to the following solution:
(define l (list 1 2 3 4))
(define (reverse lista)
(car (cons (reverse (cdr (cons 0 lista))) 0)))
(display (reverse l))
Although it works I don't really understand why it works.
In my head, it would evaluate to a series of nested cons until cons of () (which the cdr of a list with one element).
I guess I am not understanding the substitution model, could someone explain me why it works?
Obs:
It is supposed to work only in not nested lists.
Taken form SICP, exercise 2.18.
I know there are many similar questions, but as far as I saw, none presented
this solution.
Thank you
[As this happens quite often, I write the answer anyway]
Scheme implementations do have their builtin versions of reverse, map, append etc. as they are specified in RxRS (e.g. https://www.cs.indiana.edu/scheme-repository/R4RS/r4rs_8.html).
In the course of learning scheme (and actually any lisp dialect) it's really valuable to implement them anyway. The danger is, one's definition can collide with the built-in one (although e.g. scheme's define or lisp's label should shadow them). Therefore it's always worth to call this hand-made implementation with some other name, like "my-reverse", "my-append" etc. This way you will save yourself much confusion, like in the following:
(let ([append
(lambda (xs ys)
(if (null? xs)
ys
(cons (car xs) (append (cdr xs) ys))))])
(append '(hello) '(there!)))
-- this one seems to work, creating a false impression that "let" works the same as "letrec". But just change the name to "my-append" and it breaks, because at the moment of evaluating the lambda form, the symbol "my-append" is not yet bound to anything (unlike "append" which was defined as a builtin procedure).
Of course such let form will work in a language with dynamic scoping, but scheme is lexical (with the exception of "define"s), and the reason is referential transparency (but that's so far offtopic that I can only refer interested reader to one of the lambda papers http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf).
This reads pretty much the same as the solutions in other languages:
if the list is empty, return an empty list. Otherwise ...
chop off the first element (CAR)
reverse the remainder of the list (CDR)
append (CONS) the first element to that reversal
return the result
Now ... given my understanding from LISP days, the code would look more like this:
(append (reverse (cdr lista)) (list (car lista)))
... which matches my description above.
There are several ways to do it. Here is another:
(define my-reverse
(lambda (lst)
(define helper
(lambda (lst result)
(if (null? lst)
result
(helper (cdr lst) (cons (car lst) result)))))
(helper lst '())))

How do I stop recursion and return something in racket?

NOTE: I would like to do this without rackets built in exceptions if possible.
I have many functions which call other functions and may recursively make a call back to the original function. Under certain conditions along the way I want to stop any further recursive steps, and no longer call any other functions and simply return some value/string (the stack can be ignored if the condition is met).. here is a contrived example that hopefully will show what I'm trying to accomplish:
(define (add expr0 expr1)
(cond
[(list? expr0) (add (cadr expr0) (cadr (cdr expr0)))]
[(list? expr1) (add (cadr expr1) (cadr (cdr expr1)))]
[else (if (or (equal? expr0 '0) (equal? expr1 '0))
'(Adding Zero)
(+ expr0 expr1))]
))
If this were my function and I called it with (add (add 2 0) 3), Then the goal would be to simply return the entire string '(Adding Zero) ANYTIME that a zero is one of the expressions, instead of making the recursive call to (add '(Adding Zero) 3)
Is there a way to essentially "break" out of recursion? My problem is that if i'm already deep inside then it will eventually try to evaluate '(Adding Zero) which it doesn't know how to do and I feel like I should be able to do this without making an explicit check to each expr..
Any guidance would be great.
In your specific case, there's no need to "escape" from normal processing. Simply having '(Adding Zero) in tail position will cause your add function to return (Adding Zero).
To create a situation where you might need to escape, you need something a
little more complicated:
(define (recursive-find/collect collect? tree (result null))
(cond ((null? tree) (reverse result))
((collect? tree) (reverse (cons tree result)))
((not (pair? tree)) (reverse result))
(else
(let ((hd (car tree))
(tl (cdr tree)))
(cond ((collect? hd)
(recursive-find/collect collect? tl (cons hd result)))
((pair? hd)
(recursive-find/collect collect? tl
(append (reverse (recursive-find/collect collect? hd)) result)))
(else (recursive-find/collect collect? tl result)))))))
Suppose you wanted to abort processing and just return 'Hahaha! if any node in the tree had the value 'Joker. Just evaluating 'Hahaha! in tail position
wouldn't be enough because recursive-find/collect isn't always used in
tail position.
Scheme provides continuations for this purpose. The easiest way to do it in my particular example would be to use the continuation from the predicate function, like this:
(call/cc
(lambda (continuation)
(recursive-find/collect
(lambda (node)
(cond ((eq? node 'Joker)
(continuation 'Hahaha!)) ;; Processing ends here
;; Otherwise find all the symbols
;; in the tree
(else (symbol? node))))
'(Just 1 arbitrary (tree (stucture) ((((that "has" a Joker in it)))))))))
A continuation represents "the rest of the computation" that is going to happen after the call/cc block finishes. In this case, it just gives you a way to escape from the call/cc block from anywhere in the stack.
But continuations also have other strange properties, such as allowing you to jump back to whatever block of code this call/cc appears in even after execution has left this part of the program. For example:
(define-values a b (call/cc
(lambda (cc)
(values 1 cc))))
(cc 'one 'see-see)
In this case, calling cc jumps back to the define-values form and redefines a and b to one and see-see, respectively.
Racket also has "escape continuations" (call/ec or let/ec) which can escape from their form, but can't jump back into it. In exchange for this limitation you get better performance.

Recursively check for atoms in a list

I am attempting to write a small recursive program that tests a list and returns t if every element is an atom. The problem I am having is that when the function receives an empty list, it returns t instead of the desired result of nil. I cannot come up with a way to have it return nil for an initially empty list and still function properly in a recursive manner.
(defun only-atoms (in)
(if (null in)
t
(and (atom (first in)) (only-atoms (cdr in)) )
)
)
The function can be implemented without recursion using e.g. every, as in:
(defun only-atoms (list)
(and list (every #'atom list)))
When it comes to your stated problem that the function returns T instead of the desired result of NIL when the function is called with an empty list:
Your recursive implementation explicitly returns T if (null in) is true, which explains your finding. Simply change it to the desired value NIL. Consider changing the if construct to and.
Only make the recursive call when the list has more than one item. A well placed test for (rest in) will do. Provide a true value instead of making the recursive call if the list is at its last item.
Carefully locate the only-atoms call to ensure that the function can be tail-recursive.
For example:
(defun only-atoms (list)
(and list
(atom (first list))
(or (null (rest list))
(only-atoms (rest list)))))
Use COND, which allows you to test for several cases:
empty list -> nil
one element list -> atom? ; hint: don't use LENGTH
else -> atom? for first element and recursive call for rest elements
The empty list does fulfill the condition that every element is an atom! Your requirement that it should contain at least one element is an additional requirement.
The simplest way to express "every element of the list is an atom" is (every #'atom list). You can combine it with your additional requirement with and.
If you insist on doing it recursively in SICP-style, separate your requirements:
(defun not-empty-and-all-atoms (list)
(and list
(all-atoms list)))
(defun all-atoms (list)
(if (endp list)
t
(and (atom (first list))
(all-atoms (rest list)))))
This solution works correctly:
(defun lat-p (lst)
(labels ((lat-p* (lst)
(cond
((null lst) t)
((atom (car lst)) (lat-p* (cdr lst)))
(t nil))))
(if lst
(lat-p* lst)
nil)))
However a much more elegant solution(with no recursion) would be:
(defun lat-p (lst)
(and lst (every #'atom lst)))
You can split your function in two, and provide the initial nil screening before you enter recursion. The following code is one way to do so (I tried to keep it as close to provided code as possible):
(defun only-atoms (in)
(defun only-atoms-iter (in)
(if (null in)
t
(and (atom (first in)) (only-atoms-iter (cdr in)))))
(unless (null in)
(only-atoms-iter in)))
This is also a good opportunity to make your function tail recursive:
(defun only-atoms (in)
(defun only-atoms-iter (in state)
(if (null in)
state
(only-atoms-iter (cdr in) (and state (atom (first in))))))
(unless (null in)
(only-atoms-iter in t)))

Scheme List Manipulation (Recursion)

The basic problem here is, when given a list, to return all elements of that list other than the last element. For example, given (a b c d) --> return (a b c). I essentially have the function, it's just the Scheme syntax that I'm having trouble with and Google isn't being very friendly. I'm not sure if I'm using cons correctly.
(define all-but-last
(lambda (x)
(if (null? (cdr x))
('()))
(cons ((car x) (all-but-last(cdr x)))
)))
Someone who's knowledgeable with r5rs scheme syntax would be helpful. Thanks!
If you remove the extra parentheses around the '() and arguments to cons, the code will work (for non-empty input lists).
Using DrRacket with Language R5RS, this works:
(define all-but-last
(lambda (x)
(if (null? x)
'()
(if (null? (cdr x))
'()
(cons (car x) (all-but-last(cdr x)))))))
An alternative solution:
(define (all-but-last xs)
(reverse
(rest
(reverse xs))))
See the answers to this question:
removing last element of a list(scheme)
Also, I'm going to tag this one as "homework". If it's not, let me know and I'll remove it.
if you pass '() to your function, I think you should give error message other than return '()

Is it possible to rewrite recursive function as macro in lisp?

I wrote this quicksort function:
(defun quicksort (lst)
(if (null lst)
nil
(let ((div (car lst))
(tail (cdr lst)))
(append (quicksort (remove-if-not (lambda (x) (< x div)) tail))
(list div)
(quicksort (remove-if (lambda (x) (< x div)) tail))))))
but I can't rewrite it as macro, it does not work, nor does, for example, this simple foo (recursive sum - I know, a little silly, but just as example):
(defun Suma (lst)
(if (cdr lst)
(+ (Suma (cdr lst))
(car lst))
(car lst)))
works properly, but the macro:
(defmacro SumaMacro (lst)
'(if (cdr lst)
'(+ (prog (SUMAMACRO (cdr lst)))
(prog (car lst)))
'(car lst)))
seems to be wrong. Does someone have any suggestions about rewriting recursive functions as macro?
You're mixing macro and runtime; or in other words, you're mixing values and syntax. Here's a very simple example:
(defmacro while (condition &body body)
`(when ,condition ,#body (while ,condition ,#body)))
The bad thing here is that the macro doesn't execute the body, it just constructs a piece of code with the given body in it. So, when there's that kind of a loop in a function, it's protected by some conditional like if which will prevent an infinite loop. But in this macro code there is no such condition -- you can see that the macro expands into the exact original form, which means that it's trying to expand into some infinite piece of code. It's just as if you've written
(defun foo (blah)
(cons 1 (foo blah)))
then hooked that generator function into the compiler. So to do these kinds of runtime loops, you'll have to use a real function. (And when that's needed, you can use labels to create a local function to do the recursive work.)
It makes no sense to write recursive functions like SUM or QUICKSORT as macros. Also, no, in general it is not possible. A macro expands source code. At compile time the macro sees only the source code, but not the real arguments the code is being called with. After compilation the macros is gone and replaced with the code it produces. This code then later gets called with arguments. So the macro can't do computation at compile time, based on argument values that are known only at runtime.
The exception is: when the argument value is known at compile time / macro expansion time, then the macro can expand to a recursive macro call to itself. But that is really advanced macro usage and nothing that one would add to code to be maintained by other programmers.
Rule of thumb: If you want to do recursive computations, then use functions. If you want to process source code, then use a macro.
Also, try to use Lisp-like formatting. The editor counts the parentheses, does highlighting and indentation. Don't put parentheses on their own lines, they feel lonely there. The usual Lisp style is more compact and uses also the horizontal space more. If you work with lists, then use FIRST and REST, instead of CAR and CDR.
Your 'suma' function would look like this:
(defun suma (list)
(if (rest list)
(+ (suma (rest list))
(first list))
(first list)))
Forget about the macro. But, if you want to learn more about macros, then the book 'On Lisp' by Paul Graham (available as a download) is a good source of knowledge.

Resources