I am trying to make a math-expression interpreter for a project, but I have difficulty in parsing unusual (unary) expressions like '(- -1), '(- (- -1)), '(* 10), '(/ 10) and other similar expressions.
(define (math-eval expr)
(define (helper op expr)
(cond [(and (or (eqv? + op) (eqv? - op)) (null? expr)) 0]
[(and (or (eqv? * op) (eqv? / op)) (null? expr)) 1]
[(eqv? '+ (car expr)) (helper + (cdr expr))]
[(eqv? '- (car expr)) (helper - (cdr expr))]
[(eqv? '* (car expr)) (helper * (cdr expr))]
[(eqv? '/ (car expr)) (helper / (cdr expr))]
[(atom? (car expr))
(op (car expr) (helper op (cdr expr)))]
[else (+ (helper + (car expr)) (helper + (cdr expr)))]))
(helper + expr))
This function accepts list and I think that the problem is in the atom? option, but I am not sure how to fix it.
I would be very thankful if you could help me or give me directions how to solve my problem.
Try to build math-eval recursively:
If expr is number, return that number.
If expr is symbol of function, return that function.
If expr is list, evaluate each element of list and then use apply to call function (first element of list, car) on numbers (rest of elements, cdr).
Here is helper function, which returns function for given symbol:
(define (fetch-function expr)
(second
(assoc expr (list (list '+ +)
(list '- -)
(list '* *)
(list '/ /)))))
Examples:
> (fetch-function '+)
#<procedure:+>
> (fetch-function '-)
#<procedure:->
And here is recursive math-eval, working as described:
(define (math-eval expr)
(cond ((number? expr) expr)
((symbol? expr) (fetch-function expr))
(else (let ((op (car expr))
(args (cdr expr)))
(apply (math-eval op)
(map math-eval args))))))
Examples:
> (math-eval '(- -1))
1
> (math-eval '(- (- -1)))
-1
> (math-eval '(* 10))
10
> (math-eval '(/ 10))
1/10
Related
Getting an error for my binary search tree that I created in scheme.
$gosh main.sc
*** ERROR: list required, but got 5
Stack Trace:
_______________________________________
This is my code. I think the error has to do with how I am calling the functions, but I am not sure what exactly is wrong. I am calling the insert function with the two required parameters: tree, and a value of 5.
(define (member? t v)
(cond
((null? t)
#f
)
((< node (car t))
(member? (cadr t) v))
((> node (car t))
(member? (caddr t) v))
(else
#t
)
)
)
(define (insert t v)
(cond
((null? t)
(list v '() '())
)
((< v (car t))
(list (car t) (insert (cadr t) v) (caddr t))
)
((>= v (car t))
(list (car t) (cadr t) (insert (caddr t) v))
)
(else
t
)
)
)
(define (fold func val lst)
(if (null? lst) val (fold func (func val (car lst)) (cdr lst))))
(define (build lst)
(fold (lambda (t v) (insert t v)) '() lst))
(define t (list 10 '() '()))
(insert t 5)
display (member t 5)
display t
You care calling (member t 5) which is the same as (member '(10 '() '()) 5). Now member is not the same as your defined member? since it has a different name. member is the core library that looks like this:
(define (member obj lst)
(cond ((null? lst) #f)
((equal? obj (car lst)) lst)
(else (member obj (cdr lst)))))
Your member? has the two parameters swapped so when you miswrote the name and used the report version member 5 is not null, then it will do (car 5) and that will fail miserably. The error message that 5 is not of the required type list is pretty decent. It might spell the beans that it was member that failed though.
Another thing. If you replace the call to member with a call to member? you hit more problems. You use a variable node that is not defined anywhere.
The indentation and placing of parentheses is not goo lisp style. Your code should be written like this:
;; node doesn't exist in OPs code, but my implementation doesn't like member? without it
(define node 5)
;; possible typo by using the variable node ?
(define (member? t v)
(cond
((null? t)
#f)
((< node (car t))
(member? (cadr t) v))
((> node (car t))
(member? (caddr t) v))
(else
#t)))
(define (insert t v)
(cond
((null? t)
(list v '() '()))
((< v (car t))
(list (car t) (insert (cadr t) v) (caddr t)))
((>= v (car t))
(list (car t) (cadr t) (insert (caddr t) v)))
(else
t)))
(define (fold func val lst)
(if (null? lst) val (fold func (func val (car lst)) (cdr lst))))
(define (build lst)
(fold (lambda (t v) (insert t v)) '() lst))
(define t (list 10 '() '()))
(insert t 5)
;; NB doesn't call a procedure, just evaluates it.
display
;; Here the arguments are the wrong order and you don't use memeber?
(member t 5)
;; NB doesn't call a procedure, just evaluates it.
display
t
I have that Lisp function:
(defun F(l)
(cond
((atom l) -1)
((>(F(car l))0)(+(car l)(F(car l))(F(cdr l))))
(t(F(cdr l)))
)
)
and I want to prevent double invocation of recursive function (F (car l)) in the second line of cond using a lambda function.
I tried that:
(defun F(l)
((LAMBDA (ff)
(cond
((atom l) -1)
((> ff 0)(+(car l) ff (F(cdr l))))
(t(F(cdr l)))
)
) (F (car l)))
)
but I get error :
CAR: 1 is not a list
at call (F '(1 2 3 4)).
Also I'm not sure if that correctly avoids double recursive call.
The reason you are getting this error is that you are calling (car l) always, even when l is, in fact, not a list.
To avoid this, only do that when needed:
(defun F(l)
(if (atom l) -1
(let* ((l1 (car l))
(f1 (F l1))
(f2 (F (cdr l))))
(if (plusp f1)
(+ l1 f1 f2)
f2))))
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)))))
I'm finishing up a Scheme assignment and I'm having some trouble with the recursive cases for two functions.
The first function is a running-sums function which takes in a list and returns a list of the running sums i.e (summer '(1 2 3)) ---> (1 3 6) Now I believe I'm very close but can't quite figure out how to fix my case. Currently I have
(define (summer L)
(cond ((null? L) '())
((null? (cdr L)) '())
(else (cons (car L) (+ (car L) (cadr L))))))
I know I need to recursively call summer, but I'm confused on how to put the recursive call in there.
Secondly, I'm writing a function which counts the occurrences of an element in a list. This function works fine through using a helper function but it creates duplicate pairs.
(define (counts L)
(cond ((null? L) '())
(else (cons (cons (car L) (countEle L (car L))) (counts (cdr L))))))
(define (countEle L x)
(if (null? L) 0
(if (eq? x (car L)) (+ 1 (countEle (cdr L) x)) (countEle (cdr L) x))))
The expected output is:
(counts '(a b c c b b)) --> '((a 1) (b 3) ( c 2))
But it's currently returning '((a . 1) (b . 3) (c . 2) (c . 1) (b . 2) (b . 1)). So it's close; I'm just not sure how to handle checking if I've already counted the element.
Any help is appreciated, thank you!
To have a running sum, you need in some way to keep track of the last sum. So some procedure should have two arguments: the rest of the list to sum (which may be the whole list) and the sum so far.
(define (running-sum L)
(define (rs l s)
...)
(rs L 0))
For the second procedure you want to do something like
(define (count-elems L)
(define (remove-elem e L) ...)
(define (count-single e L) ...)
(if (null? L)
'()
(let ((this-element (car L)))
(cons (list this-element (count-single this-element L))
(count-elems (remove-elem this-element (cdr L)))))))
Be sure to remove the elements you've counted before continuing! I think you can fill in the rest.
To your first problem:
The mistake in your procedure is, that there is no recursive call of "summer". Have a look at the last line.
(else (cons (car L) (+ (car L) (cadr L))))))
Here is the complete solution:
(define (summer LL)
(define (loop sum LL)
(if (null? LL)
'()
(cons (+ sum (car LL)) (loop (+ sum (car ll)) (cdr LL)))))
(loop 0 LL))
Im trying to write a function called removesub* which accepts two arguments (l1 and l2). The function needs to return the second list with the first occurence of the subsequence removed. So, if the first list is '(a b c), the first a if the second list is removed, the first b that appears after the removed a is removed, and the first c that appears after the removed b is removed - no matter how deep the atoms are nested.
Working Example
Input: (removesub* '(a b) '(w (x b) ((a) ((y z))) b a))
Output: (w (x b) (() ((y z))) a)
My current attempt doesnt seem to work because I have no way of sharing the l1 argument between nested recursive calls i.e. ((pair? (car l2)) (cons (removesub* l1 (car l2)) (removesub* l1 (cdr l2)))) splits l1 into two separate instances resulting in the following result. How can I share the l1 value so every recursive calls knows if the others have found the first instance of a value in l1?
Working Example
Input: (removesub* '(a b) '(w (x b) ((a) ((y z))) b a))
Output: (w (x b) (() ((y z))) b)
Attempted Solution - Scheme
(define removesub*
(lambda (l1 l2)
(cond
((or (null? l1) (null? l2)) l2)
((pair? (car l2)) (cons (removesub* l1 (car l2)) (removesub* l1 (cdr l2))))
((eq? (car l1) (car l2)) (removesub* (cdr l1) (cdr l2)))
(else (cons (car l2) (removesub* l1 (cdr l2)))))))
You need to pass the resulting symbols to search for to the next iteration. THere are many ways to do this.
You can use a compound return in the helper
(define (removesub* elements-in-order haystack)
;; just use a pair to pass result and the
;; elements to continue searching for
(define (result eio h)
(cons eio h))
(cdr
(let rec ((eio elements-in-order)
(h haystack))
(cond ((or (not (pair? eio))
(not (pair? h)))
(result eio h))
((pair? (car h))
(let* ((r (rec eio (car h)))
(r2 (rec (car r) (cdr h))))
(result (car r2) (cons (cdr r) (cdr r2)))))
((eq? (car eio) (car h))
(rec (cdr eio) (cdr h)))
(else
(let ((r (rec eio (cdr h))))
(result (car r) (cons (car h) (cdr r)))))))))
Notice I do car first then use both parts of the result to do the next.
Scheme/Racket can return more than one value with values
(define (removesub* elements-in-order haystack)
(define (helper eio h)
(cond ((or (not (pair? eio))
(not (pair? h)))
(values eio h))
((pair? (car h))
(let*-values ([(eiocar hcar) (helper eio (car h))]
[(eiocdr hcdr) (helper eiocar (cdr h))])
(values eiocdr (cons hcar hcdr))))
((eq? (car eio) (car h))
(helper (cdr eio) (cdr h)))
(else
(let-values ([(eiocdr hcdr) (helper eio (cdr h))])
(values eiocdr (cons (car h) hcdr))))))
(let-values ([(eio result) (helper elements-in-order haystack)])
result))
Not really a semantic difference over the first, but it might be a tad faster since in theory the results can stay on the stack rather than each result having to create a cons that can be GC-ed as fast as the stack unrolls.
You can use continuation passing style:
(define (removesub* elements-in-order haystack)
(let cps ((eio elements-in-order)
(h haystack)
(c (lambda (eio h) h)))
(cond ((or (not (pair? eio))
(not (pair? h)))
(c eio h))
((pair? (car h))
(cps eio
(car h)
(lambda (eio hcar)
(cps eio
(cdr h)
(lambda (eio hcdr)
(c eio (cons hcar hcdr)))))))
((eq? (car eio) (car h))
(cps (cdr eio) (cdr h) c))
(else
(cps eio
(cdr h)
(lambda (eio res)
(c eio (cons (car h) res))))))))
This works by the helper has a continuation argument. This is close to what many Scheme implementations actually do to your code before running.
You can use mutation
Probably the fastest and easiest, but then you need to use #!r6rs or another standard Scheme rather than #!racket as implementation language.