Scheme Recursion Loop Incorrect Values and Variable Binding - recursion

I started a question here about a hangman game I am working on.
Recursive Scheme Function Value Error
I feel that the hangman portion is confusing people from my real issue and question. My problem is, I call various defined functions from within my recursion loop and get incorrect values. When I call these same function by themselves (not in a recursive loop) they work as expected. I know it is either something I am overlooking or a variable binding issue is going on that I need a workaround for.
First here a reproduction of the problem code:
(define (recurse a_list a_number)
(cond ((= a_number 0)
(display "Zero Condition.")
)
(else
(display "\n\n")
(display-list a_list ",")
(display "\n")
(display (car a_constant))
(display "\n")
(display "If the above letter is in the list, result should be true\n")
(display (contains? a_list (car a_constant)))
(display "\n")
(display "Enter a letter:")
(recurse (cons (symbol->string (read)) a_list) (- a_number 1))
)
)
)
Here are my definitions used inside the recursive loop:
(define (display-list a_list separater)
(if (null? a_list)
(display "")
(begin
(display (car a_list))
(if (null? (cdr a_list))
(display "")
(display separater))
(display-list (cdr a_list) separater)
)
)
)
(define (contains? list item)
;(display "\n")
;(display list)
;(display "\n")
;(display item)
;(display "\n")
(cond ((empty? list)
#f
)
((eq? (first list) item)
#t
)
(else
(contains? (rest list) item)
)
)
)
(define a_constant '("n" "o" "t" "w" "o" "r" "k" "i" "n" "g"))
(define test_li_1 '("n" "b"))
(define test_li_2 '("a" "b"))
This is what I ran:
> (contains? a_constant (car test_li_1))
#t
> (contains? a_constant (car test_li_2))
#f
It works as expected.
When I run the recursive Loop this is what I get:
> (recurse test_li_2 2)
a,b
n
If the above letter is in the list, result should be true
#f
Enter a letter:n
n,a,b
n
If the above letter is in the list, result should be true
#f
In my mind, the first output is correct, but the second one is not.
When I run with test_li_1 it always evaluates to true which, it should since 'n' is always in my a_list. What I have put together through several tests, is the recursive function keeps using my initially passed in list and does not use the appended version for function calls, which is not what I want it to do. I also think that is not how it should work right? Shouldn't my passed in value be used and not a value from several recursive levels up? I'm testing this all in Dr. Racket with #lang racket in case that matters.

The problem reported occurs because you're using eq? to test for string equality. From the documentation:
(eq? v1 v2) → boolean? : Return #t if v1 and v2 refer to the same object, #f otherwise.
So you see, eq? is testing for identity, not for equality. For that, you should use string=? or equal?. Modify the contains? procedure as follows, and it'll work:
(define (contains? list item)
(cond
((empty? list) #f)
((string=? (first list) item) #t)
(else (contains? (rest list) item))))

When you call (symbol->string (read)) and enter in a, you get a fresh string "a". This is a new string object that is not eq? to any "a" in your program. Try this to see the problem:
(eq? (symbol->string (read)) "a")
If you enter in a, this will output #f because the two string items are separate objects. You've run afoul of string interning. All instances of "a" written in your source code are stored as references to one object upon compilation, so (eq? "a" "a") will evaluate to true. When you (read) input as strings, those strings will be freshly created objects and won't be equal to any other strings. There are two ways you can fix this:
Use string=? for comparison instead of eq? (as in Oscar's answer)
Use lists of characters instead of lists of single-character strings, e.g. '(#\a #\b #\c) is the string "abc". From the Racket documentation of characters:
Two characters are eqv? if they correspond to the same scalar value. For each scalar value less than 256, character values that are eqv? are also eq?
Letter characters (a-z and A-Z) have values less than this in Racket's Unicode encoding, so any letter characters you read in will not run afoul of the eq? issue. This brings up another point - you should be sanitizing your input from read. The read procedure is not guaranteed to return a string, in particular if I enter in 1 instead of a string, it returns the number 1, not the string "1". You should add some logic to handle bad input, or this will crash your program.

Related

LISP Cannot take CAR of T

I am trying to evaluate each atom of a list and see if it's equal to the number provided and remove if its not but I am running into a slight problem.
I wrote the following code:
(defun equal1(V L)
(cond((= (length L) 0))
(T (cond( (not(= V (car(equal1 V (cdr L))))) (cdr L) )))
)
)
(equal1 5 '(1 2 3 4 5))
I obtain the following error
Error: Cannot take CAR of T.
If I add (write "hello") for the action if true, the following error is obtained:
Error: Cannot take CAR of "hello".
I'm still quite new to LISP and was wondering what exactly is going on and how could I fix this so I could evaluate each atom properly and remove it if its not, thus the cdr L for the action.
car and cdr are accessors of objects of type cons. Since t and "hello" are not cons you get an error message.
To fix it you need to know what types your function returns and not car unless you know that it's a cons
EDIT
First off ident and clean up the code.. The nested cond are uneccesary since cond is a if-elseif-else structure by default:
(defun remove-number (number list)
(cond ((= (length list) 0)
t)
((not (= number (car (remove-number number (cdr list)))))
(cdr list))))
(t
nil)))
I want you to notice I've added the default behaviour of returning t when a consequent is not given as we know = returns either t or nil so it returns t when the length is 0 in this case.
I've added the default case where none of the two previous predicates were truthy and it defaults to returning nil.
I've named it according to the functions used. = can only be used for numeric arguments and thus this will never work on symbols, strings, etc. You need to use equal if you were after values that look the same.
Looking at this now we can see that the functions return value is not very easy to reason about. We know that t, nil and list or any part of the tail of list are possible and thus doing car might not work or in the case of (car nil) it may not produce a number.
A better approach to doing this would be:
check if the list is empty, then return nil
check if the first element has the same numeric value as number, then recurse with rest of the list (skipping the element)
default case should make cons a list with the first element and the result fo the recursion with the rest of the list.
The code would look something like this:
(defun remove-number (number list)
(cond ((endp list) '())
((= (car list) number) (remove-number ...))
(t (cons ...))))
There are a couple of things you could do to improve this function.
Firstly, let's indent it properly
(defun equal1 (V L)
(cond
((= (length L) 0))
(T (cond
((not (= V (car (equal1 V (cdr L))))) (cdr L))))))
Rather than saying (= (length l) 0), you can use (zerop (length l)). A minor sylistic point. Worse is that branch returns no value. If the list L is empty what should we return?
The issue with the function is in the T branch of the first cond.
What we want to do is
remove any list item that is the same value as V
keep any item that is not = to V
The function should return a list.
The expression
(cond
((not (= V (car (equal1 V (cdr L))))) (cdr L)))
is trying (I think) to deal with both conditions 1 and 2. However it's clearly not working.
We have to recall that items are in a list and the result of the equal function needs to be a list. In the expression above the result of the function will be a boolean and hence the result of the function call will be boolean.
The function needs to step along each element of the list and when it sees a matching value, skip it, otherwise use the cons function to build the filtered output list.
Here is a skeleton to help you out. Notice we don't need the embedded cond and just have 3 conditions to deal with - list empty, filter a value out, or continue to build the list.
(defun equal-2 (v l)
(cond
((zerop (length L)) nil)
((= v (car l)) <something goes here>) ;skip or filter the value
(t (cons (car l) <something goes here>)))) ;build the output list
Of course, this being Common Lisp, there is a built-in function that does this. You can look into remove-if...

Scheme Trying to check if a word in the list

I have a few functions.
(define adjs '(black brown fast hairy hot quick red slow))
(define adj?
(lambda (a) (if (member a adjs) #t #f)
)
(define OK
(lambda (x)
(cond
((equal? x()) #t)
((equal? adj? (car x)) OK(cdr x))
((else x #f))
)
)
)
The function adj? is checking to see if the input is part of the list of adjectives in adjs.
What I am trying to do with the OK function is the user will input a list and have that list run through adj? to see if it is part of the adjs list.
What happens when I run the function is I get an error return that says I entered in "X" amount of arguments when the function only expected two. Why?
There are problems with the parentheses. Some are unnecessary and others are missing, for example when you recursively call the OK procedure, or in the way you're calling adj? - remember, in Scheme we call a procedure like this: (f x), not like this: f(x). Also, the base case of the recursion seems off, and the else clause is used incorrectly. Try this:
(define adj?
(lambda (a)
(if (member a adjs) #t #f)))
(define OK
(lambda (x)
(cond
((null? x) #t)
((adj? (car x)) (OK (cdr x)))
(else #f))))

Lisp: How to print out the recursive function to print each item in the list and sublist without quotes and return the number of items?

I want my function to print each item in the list and sublist without quotes and return the number of items. The output of the list also needs to be in order, but my function is printing in reverse. I'm not sure why, is there any reasons why? Any suggestions to how I can recursively count the number of items and return that number? In addition why is the last item printed is supposed to be 9.99 instead of 100.999?
Edit: Thanks for the help so far. Just last question: Is there a way to make any output like DAY to be in lower case (day), or is that something that can't be done?
My function:
(defun all-print (inlist)
(cond
((not (listp inlist))
(format t "Error, arg must be a list, returning nil")
())
((null inlist) 0)
((listp (car inlist))
(ffn (append (car inlist)(cdr inlist))))
(t
(format t "~a " (car inlist) (ffn (cdr inlist))))))
My output example:
CL-USER 1 > (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
100.999 -5.9 DAY -10 9 3 night 5
NIL
What it's suppose to output example:
5 night 3 9 -10 day -5.9 9.99 ;print
8 ;returns
It looks like all-print is supposed to be called ffn, since it looks like those are supposed to be recursive calls. In the rest of this answer, I'm just going to use ffn since it's shorter.
Why the output is in reverse
At present, your final cond clause makes the recursive call before doing any printing, because your recursive call is an argument to format:
(format t "~a " (car inlist) (ffn (cdr inlist)))
; ------------ -----------------
; 3rd 4th
All the arguments to format, including the 4th in this case, are evaluated before format is called. The 4th argument here will print the rest of the list, and then format will finally print the first element of the list. Your last cond clause should do the printing, and then make the recursive call:
(cond
…
(t
(format t "~a " (car inlist))
(ffn (cdr inlist))))
Why you get 100.999 rather than 9.99
You're getting 100.999 in your output rather than 9.99 (or something close to it) because the value of (* 100.999) is simply the value of 100.999. I'm guessing that you wanted (* 10 0.999) (note the space between 10 and 0.99). That still won't be quite 9.99 because of floating point arithmetic, though, but it will be close.
How to get the number of elements printed
uselpa's answer provides a good solution here. If you're supposed to return the number of elements printed, then every return value from this function should be a number. You have four cases,
not a list — returning nil is not a great idea. If this can't return a number (e.g., 0), then signal a real error (e.g., with (error "~A is not a list" inlist).
inlist is empty — return 0 (you already do)
(car inlist) is a list — here you make a recursive call to ffn. Since the contract says that it will return a count, you're fine. This is one of the reasons that it's so important in the first case (not a list) that you don't return a non-number; the contract depends on every call that returns returning an number.
In the final case, you print one item, and then make a recursive call to ffn. That recursive call returns the number of remaining elements that are printed, and since you just printed one, you need to add one to it. Thus the final cond clause should actually be something like the following. (Adding one to something is so common that Common Lisp has a 1+ function.)
(cond
…
(t
(format t "~a " (car inlist))
(1+ (ffn (cdr inlist))))) ; equivalent to (+ 1 (ffn (cdr inlist)))
A more efficient solution
We've addressed the issues with your original code, but we can also ask whether there are better approaches to the problem.
Don't append
Notice that when you have input like ((a b c) d e f), you create the list (a b c d e f) and recurse on it. However, you could equivalently recurse on (a b c) and on (d e f), and add the results together. This would avoid creating a new list with append.
Don't check argument types
You're checking that the input is a list, but there's really not much need to do that. If the input isn't a list, then using list processing functions on it will signal a similar error.
A new version
This is somewhat similar to uselpa's answer, but I've made some different choices about how to handle certain things. I use a local function process-element to handle elements from each input list. If the element is a list, then we pass it to print-all recursively, and return the result of the recursive call. Otherwise we return one and print the value. (I used (prog1 1 …) to emphasize that we're returning one, and printing is just a side effect. The main part of print-all is a typical recursion now.
(defun print-all (list)
(flet ((process-element (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x)))))
(if (endp list)
0
(+ (process-element (first list))
(print-all (rest list))))))
Of course, now that we've pulled out the auxiliary function, the iteration is a bit clearer, and we see that it's actually a case for reduce. You might even choose to do away with the local function, and just use a lambda function:
(defun print-all (list)
(reduce '+ list
:key (lambda (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x))))))
Here's my suggestion on how to write this function:
(defun all-print (lst)
(if (null lst)
0 ; empty list => length is 0
(let ((c (car lst))) ; bind first element to c
(if (listp c) ; if it's a list
(+ (all-print c) (all-print (cdr lst))) ; recurse down + process the rest of the list
(progn ; else
(format t "~a " c) ; not a list -> print item, then
(1+ (all-print (cdr lst)))))))) ; add 1 and process the rest of the list
then
? (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
5 night 3 9 -10 DAY -5.9 100.999
8

Scheme - do iterative - return value

I trying to write a function which gets an integer number , represented by string , and check if all his chars are digits and return #t \ #f accordingly . Thats the code -
(define (splitString str) (list->vector (string->list str)))
(define myVector 0)
(define flag #t)
(define (checkIfStringLegal str) (
(set! myVector (splitString str))
(do ( (i 0 (+ i 1)) ) ; init
((= i (vector-length myVector)) flag) ; stop condition
(cond ((>= 48 (char->integer (vector-ref myVector i)) ) (set! flag #f))
((<= 57 (char->integer (vector-ref myVector i)) )(set! flag #f))
)
)
)
)
Few explanations -
(list->vector (string->list str)) - convert string the char list .
(vector-ref myVector i) - char from the myVector at place i .
Its run OK , but when I try to use this func , like (checkIfStringLegal "444") I get -
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
#t
Try this:
(define (checkIfStringLegal str)
(andmap char-numeric?
(string->list str)))
This is how the procedure works:
It transforms the string into a list of characters, using string->list
It validates each character in the list to see if it's a number, applying the predicate char-numeric? to each one
If all the validations returned #t, andmap will return #t. If a single validation failed, andmap will return #f immediately
That's a functional-programming solution (and after all, this question is tagged as such), notice that your intended approach looks more like a solution in a C-like programming language - using vectors, explicit looping constructs (do), mutation operations (set!), global mutable definitions ... that's fine and it might eventually work after some tweaking, but it's not the idiomatic way to do things in Scheme, and it's not even remotely a functional-programming solution.
EDIT:
Oh heck, I give up. If you want to write the solution your way, this will work - you had a parenthesis problem, and please take good notice of the proper way to indent and close parenthesis in Scheme, it will make your code more readable for you and for others:
(define (splitString str) (list->vector (string->list str)))
(define myVector 0)
(define flag #t)
(define (checkIfStringLegal str)
(set! myVector (splitString str))
(do ((i 0 (+ i 1)))
((= i (vector-length myVector)) flag)
(cond ((>= 48 (char->integer (vector-ref myVector i)))
(set! flag #f))
((<= 57 (char->integer (vector-ref myVector i)))
(set! flag #f)))))
Even so, the code could be further improved, I'll leave that as an exercise for the reader:
Both conditions can be collapsed into a single condition, using an or
The exit condition should be: end the loop when the end of the vector is reached or the flag is false

Adding numbers from a list (e.g. asdf125dkf will return 8)

I need a function that will take in a list of characters and numbers, and then return the numbers added up (ignoring the characters). This is what I have so far:
(define (adder lst)
(cond
((null? lst)
0)
((number? (car lst))
(+(adder (car lst)) (adder (cdr lst))))
((char? (car lst))
((adder(cdr lst))))
))
(display (adder '(asd12sdf)))
Running it on codepad.org just displays void. I know the code is wrong because it looks wrong, but I have no idea how to fix it... How do I have the function keep track of the first number it finds and add it to the next one it finds, while skipping all characters?
In your second cond case, there's no reason to run adder on (car lst). Just adding (car list) itself to the recursive step should work.
For the last line, don't test (char? (car lst)). Just make the last line the else clause, meaning that anything BUT a number will go to the else line.
The reason you're getting void is because your input doesn't satisfy any of the cond conditions, and you have no else, so the answer is nothing (i.e. (void)).
The last mistake is in the input you're giving it. '(asd12sdf) is literally a list with one symbol named "asd12sdf". I think you want to give it '(a s d 1 2 s d f) (a list of 6 symbols and 2 numbers) which should result in 3. Notice that there's a very important difference between the symbol 'a and the character #\a.
It looks like you have the logic down, so your problem doesn't seem to be functional languages, just Scheme's syntax.
Edit: and in the last line, you have ((adder(cdr lst))) which has one too many parens wrapped around it. That will cause Scheme to attempt to evaluate the result of adder (which is a number) as a procedure (error!).
You should observe that this function is more or less sum which can be defined simply by using fold.
(define (adder lst)
(fold + 0 lst))
What does fold do? Basically, it's defined like so:
(define (fold f initial lst)
(if (null? lst)
initial
(fold f (f (car lst) initial) (cdr lst))))
(In other words, it calls f, a function of 2 arguments, on each element of lst, using the car of the lst as the first argument, and the accumulated result as the second argument to f.)
The issue here which you need to address is that + doesn't know how to operate on non-numeric values. No problem, you've already dealt with that. What happens if it's a character instead? Well, you're not adding anything to the total value, so replace it with a 0. Therefore, your solution is as simple as:
(define (adder lst)
(fold your-new-protected-+ 0 lst))
In Common Lisp:
(reduce #'+ '(1 #\a #\b 2 1 2 #\c #\d 4)
:key (lambda (item) (if (numberp item) item 0)))
or
(loop for item in '(1 #\a #\b 2 1 2 #\c #\d 4)
when (numberp item) sum item)

Resources