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)))
Related
I've written two versions of a lisp function. The main difference between the two is that one is done with recursion, while the other is done with iteration.
Here's the recursive version (no side effects!):
(defun simple-check (counter list)
"This function takes two arguments:
the number 0 and a list of atoms.
It returns the number of times the
atom 'a' appears in that list."
(if (null list)
counter
(if (equal (car list) 'a)
(simple-check (+ counter 1) (cdr list))
(simple-check counter (cdr list)))))
Here's the iterative version (with side effects):
(defun a-check (counter list)
"This function takes two arguments:
the number 0 and a list of atoms.
It returns the number of times the
atom 'a' appears in that list."
(dolist (item list)
(if (equal item 'a)
(setf counter (+ counter 1))
(setf counter (+ counter 0))))
counter)
As far as I know, they both work. But I'd really like to avoid side-effects in the iterative version. Two questions I'd like answered:
Is it possible to avoid side effects and keep iteration?
Assuming the answer to #1 is a yes, what are the best ways to do so?
For completeness, note that Common Lisp has a built-in COUNT:
(count 'a list)
In some ways, the difference between side-effect or no side-effect is a bit blurred. Take the following loop version (ignoring that loop also has better ways):
(loop :for x :in list
:for counter := (if (eq x 'a) (1+ counter) counter)
:finally (return counter))
Is counter set at each step, or is it rebound? I. e., is an existing variable modified (like in setf), or is a new variable binding created (as in a recursion)?
This do version is very much like the recursive version:
(do ((list args (rest list))
(counter 0 (+ counter (if (eq (first list) 'a) 1 0))))
((endp list) counter))
Same question as above.
Now the “obvious” loop version:
(loop :for x :in list
:count (eq x 'a))
There isn't even an explicit variable for the counter. Are there side-effects?
Internally, of course there are effects: environments are created, bindings established, and, especially if there is tail call optimization, even in the recursive version destroyed/replaced at each step.
I see as side effects only effects that affect things outside of some defined scope. Of course, things appear more elegant if you can also on the level of your internal definition avoid the explicit setting of things, and instead use some more declarative expression.
You can also iterate with map, mapcar and friends.
https://lispcookbook.github.io/cl-cookbook/iteration.html
I also suggest a look at remove-if[-not] and other reduce and apply:
(length (remove-if-not (lambda (x) (equal :a x)) '(:a :b :a))) ;; 2
Passing counter to the recursive procedure was a means to enable a tail recursive definition. This is unnecessary for the iterative definition.
As others have pointed out, there are several language constructs which solve the stated problem elegantly.
I assume you are interested in this in a more general sense such as when you cannot find
a language feature that solves a problem directly.
In general, one can maintain a functional interface by keeping the mutation private as below:
(defun simple-check (list)
"return the number of times the symbol `a` appears in `list`"
(let ((times 0))
(dolist (elem list times)
(when (equal elem 'a)
(incf times)))))
I'm new to Racket and I'm trying to define a function that takes a list of divisors and a list of numbers to test, and applies direct recursion and a function 'drop-divisible' for each element in the list of divisors.
I defined a function drop-divisible which takes a number and a list of numbers, and returns a new list containing only those numbers not "non-trivially divisible" by the number. This function is not the problem, it works. So what I have trouble with is the function who is gonna call this function, and itself.
Here is what I've come up with. I can imagine that this is far from correct, but I have no idea what to do.
(define (sieve-with divisors testlist)
(if (null? divisors)
'()
(begin
(drop-divisible (first divisors) testlist)
(sieve-with (rest divisors) testlist))))
You need to use tail recursion:
(define (sieve-with divisors list)
(cond [(empty? divisors) list]
[else (sieve-with (rest divisors)
(drop-divisible (first divisors) list))]))
Also, stay away from begin as much as possible. Stick to the functional paradigm.
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 '())))
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.
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.