Scheme if statement. Why does this display statement not run? - functional-programming

I am running the following code:
(define (myignore x)
0
)
(define (myinterpreter mylist)
(evaluate mylist)
)
(define (evaluate mylist)
(if (eqv? (car mylist) 'prog)
(evaluate (cdr mylist))
(display (integer? (car mylist)))
(if (integer? (car mylist))
(display "YESSS")
)
)
(if (eqv? (car mylist) 'myignore)
(myignore (cdr mylist))
)
)
(myinterpreter '(prog 5))
I am wondering why the line containing (display ("YESSS")) does not run despite the (display (integer? (car mylist))) equaling true right before the line runs?

The syntax of if is:
(if predicate
consequent
optional-alternative)
In your code, consequent is (evaluate (cdr mylist)) and optional-alternative is (display (integer? (car mylist))). Everything after that is ignored.
If you want to execute multiple expressions, you have to wrap them in begin.
(define (evaluate mylist)
(if (eqv? (car mylist) 'prog)
(evaluate (cdr mylist))
(begin
(display (integer? (car mylist)))
(if (integer? (car mylist))
(display "YESSS")
)
)
)
(if (eqv? (car mylist) 'myignore)
(myignore (cdr mylist))
)
)

Related

How to remove a list of length 1 from a nested list in lisp?

I have a nested list (1 (4 (5) 3) 9 10) and I want to delete the lists of length 1 so the result would be (1 (4 3) 9 10).
This is what I have tried so far, which does not remove (5) and returns the original list.
(defun remove (l)
(cond
((null l) nil)
((and (listp (car l)) (= (length l) 1)) (remove (cdr l)))
((atom (car l)) (cons (car l) (remove (cdr l))))
(T (cons (remove (car l)) (remove (cdr l))))
))
Two things: first, remove is a predefined function in package CL, so I strongly advice to use a different name, let's say my-remove.
Second, you are testing the length of l instead of the sublist (car l), which is what you want to eliminate.
The correct form would be:
(defun my-remove (l)
(cond
((null l) nil)
((and (listp (car l)) (= (length (car l)) 1)) (my-remove (cdr l)))
((atom (car l)) (cons (car l) (my-remove (cdr l))))
(T (cons (my-remove (car l)) (my-remove (cdr l))))
))
Tail call recursive version. Plus: Without the test (atom (car l)) to be permissive for non-list and non-atom components in the list. (e.g. vectors or other objects as element of the list - they are treated like atoms.
(defun my-remove (l &optional (acc '()))
(cond ((null l) (nreverse acc))
((listp (car l)) (if (= 1 (length (car l))) ;; list objects
(my-remove (cdr l) acc) ;; - of length 1
(my-remove (cdr l) (cons (my-remove (car l)) acc)))) ;; - longer
(t (my-remove (cdr l) (cons (car l) acc))))) ;; non-list objects

Why is this function returning true when it should be returning false?

So, I have this helper function that checks to see if there is a reflexive relationship between a list and a list of pairs.
(define helper
(lambda (L S)
(cond
((if (equal? L '()) #f ;; here, when L equals empty list, it should return #f, but somehow it returns #t even if L is '().
(if (equal? S (car (car L)))
(if (list-equal? (car L))#t
(helper (cdr L) S))
(helper (cdr L) S))))
)))
However, the part where it checks if L is an empty list returns true even if the list is an empty list, allowing my other function to return true.
I've been stumped trying to figure out why its returning #t instead of #f for hours. Please help me figure out what's making this happen.
Oh and I'm using Dr.Racket version 6.12.
EDIT: more clearly, I would like the function to return #f when L is '() as a base case so that the function doesn't need to do anymore recursion.
You put if forms within cond which is quite superfluous.
So your mistake was for sure your lack of understanding of the cond syntax.
Remember cond syntax goes like:
(cond (condition1 what-to-do-if-condition1-is-true)
(condition2 what-to-do-if-condition2-is-true)
( ... ... )
(else what-to-do-if-none-of-the-conditions-listed-above-evaluated-to-true))
So I formed your expression accordingly to:
(define helper
(lambda (L S)
(cond ((equal? L '()) #f)
((and (equal? S (car (car L))) (list-equal? (car L))) #t)
(else (helper (cdr L) S)))))
Since you didn't gave definition for list-equal? - I cannot run this code for testing.
You have nested if in cond. Lets rewrite you code som something identical:
(define helper
(lambda (L S)
(let ((result
(if (equal? L '())
#f
(if (equal? S (car (car L)))
(if (list-equal? (car L))
#t
(helper (cdr L) S))
(helper (cdr L) S)))))
(cond
(result result)
(else 'implementation-defined-value)))))
A cond will return a implementation defined value as the else clause should none of the previous predicates hit. Since your base casse returns #f it goes to the default else case.
Since the other answer show the code with cond, here is the same with if:
(define helper
(lambda (L S)
(if (equal? L '())
#f
(if (and (equal? S (car (car L)))
(list-equal? (car L)))
#t
(helper (cdr L) S)))))
You can also write this only with and and or:
(define helper
(lambda (L S)
(and (pair? L)
(or (and (equal? S (car (car L)))
(list-equal? (car L)))
(helper (cdr L) S)))))

recursive list function in lisp that finds number of times a was present in list

;Question 3
(defun listcheck(lst)
(cond
((not (null lst))
(cond
((eq (car lst) 'a) (+ (listcheck (cdr lst)) 1))
( T (listcheck (cdr lst)))
)
)
)
0
)
this function prints out 0 at all times not sure where im going wrong any input would help
It's printing 0 because the function ends with 0, outside the cond. So it returns this in all cases, not just the base of the recursion. That should only be returned when lst is null.
(defun listcheck(lst)
(cond ((null lst) 0)
((eq (car lst) 'a) (+ (listcheck (cdr lst)) 1))
(T (listcheck (cdr lst)))))

what am i doing wrong in this code? im trying to check if all the elements in a list are the same, and no matter the test cases i get a #f

Create the function AllEqual?(L) which will be given a list of (at least 2) elements and will return #t if all of them are the same, otherwise #f
(define (allequal? l)
(if (< (length l) 2)
#t
(equal? (car l) (allequal? (cdr l)))))
(equal? (car l) (allequal? (cdr l)))
tests if (car l) is equal? to (allequal? ...). Since allequal? returns a boolean (#t or #f), you test if (car l) is #t or #f, which is not what you want.
You need to compare the first two elements, if available, and then recurse on the cdr of your list:
(define (allequal? l)
(if (< (length l) 2)
#t
(and (equal? (car l) (cadr l))
(allequal? (cdr l)))))
or, easier,
(define (allequal? l)
(or (< (length l) 2)
(and (equal? (car l) (cadr l))
(allequal? (cdr l)))))
or even
(define (allequal? l)
(or (null? l)
(null? (cdr l))
(and (equal? (car l) (cadr l))
(allequal? (cdr l)))))

Avoid double recursion

(DEFUN F(L)
(COND
((NULL L) NIL)
((LISTP (CAR L))
(APPEND (F (CAR L))
(F (CDR L))
(CAR (F (CAR L)))))
(T (LIST (CAR L)))
))
This function returns a dotted pair(if the first element is a sublist) with the first element of the sublist as the right part and on the left part are the element on the right and the second element of the list(if not sublist).Now,how can I rewrite this without using the double recursion of (F (CAR L)) and without using SET,SETQ,SETF?
Use LET to bind a local variable to the repeated recursive call.
(DEFUN F(L)
(COND
((NULL L) NIL)
((LISTP (CAR L))
(LET ((FCAR (F CAR L)))
(APPEND FCAR
(F (CDR L))
(CAR FCAR))))
(T (LIST (CAR L)))
))

Resources