I tried to define this function that takes multiple integers and keeps those that are different from 0. It does not work, apparently, the recursive call (filter $?tail) does not match with the parameter list. Can this be done in CLIPS?
(deffunction filter (?head $?tail)
(if (= (length $?tail) 0) then
(if (!= ?head 0) then (return ?head))
(return $?tail))
(if (= ?head 0) then
(return (filter $?tail)))
(bind $?result ?head (filter $?tail))
(return $?result)
)
The function filter is declared with 2 parameters filter(?head $?tail) but you are calling it with only one (filter $?tail)
Is the recursion needed? This problem can be solved easily with the function delete-member$:
(delete-member$ $?list 0)
Example:
CLIPS> (delete-member$ (create$ 6 7 0 8 0 7) 0)
(6 7 8 7)
CLIPS>
Related
I understand the big picture applicative vs normal order lesson here I think, but I'm struggling with:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Eva demonstrates the program for Alyssa:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
And for that matter:
(cond (= 2 3) 0 5)
3
(cond (= 1 1) 0 5)
1
Could you walk me through like a child why these return these values? They are all just predicates with no consequent expressions, right?
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
when you call first new-if procedure as you can see you test predicate (= 2 3) if it is true it returns then-clause which is 0 and if it is not true then it returns else-clause which is 5. For second new-if procedure predicate is (= 1 1) which is true so it returns then-clause which is 0.
Actually I don't know why these cond expressions returns these values but you should normally use cond like this after cond every parenthesis includes a clause
(cond (<p1><e1>)
(<p2><e2>)
...
(<pn><en>))
for your example
(cond ((= 2 3) 0)
(5))
if there is no expression after test in the clause it returns test value as the result which is 5 here or you can call with else either
(cond ((= 2 3) 0)
(else 5))
Use the substitution method, as explained in the previous chapter.
(new-if (= 2 3) 0 5)
—> (new-if #f 0 5)
—> (cond (#f 0)
(else 5))
—> 5
and
(new-if (= 1 1) 0 5)
—> (new-if #t 0 5)
—> (cond (#t 0)
(else 5))
—> 0
Your cond examples have bad syntax, but if you have a clause like
(cond
(= 2 3)
...
it is equivalent to
(cond
(= (begin 2 3))
...
that is, the condition is =, and 2 3 is a sequence of expressions that constitute the body.
The value of such a sequence of expressions is the value of the last expression.
(The book will not use such sequences until side effects are introduced, around half way through the book.)
I don't know why this does not work. I get an error saying "Error: 1 is not a function[(anon)]"
(define (mem lst ele)
(cond ;if the list is empty return false
((null? lst) #f)
;if the first element is equal to the given element return true
;otherwise call the function with rest of the list
(else (if (= ele (car lst))
#t
(mem (cdr lst) ele)))))
(mem ’(1) ’(1 4 -2))
It works for me; how are you calling mem? I am guessing that you did something like: (mem (1 2 3 4) 1). Procedure calls always evaluate their arguments in Scheme, so in the procedure call (mem (1 2 3 4) 1) the expression (1 2 3 4) is evaluated; but lists are evaluated as if the first member is a procedure, so 1 is treated as a function; it is not, and this raises an exception.
You could quote the list: (mem (quote (1 2 3 4)) 1), or you can use the shorthand (mem '(1 2 3 4) 1). quote is a special form that does not evaluate its argument; instead it just returns whatever datum it is given. You can try this out at the REPL:
> (+ 1 2)
3
> (quote (+ 1 2))
(+ 1 2)
> '(+ 1 2)
(+ 1 2)
Here the naked expression (+ 1 2) evaluates to 3, but the quoted expressions just return the expressions given to quote. That is, (quote (+ 1 2)) evaluates to the expression (+ 1 2), not to the result of evaluating the expression (+ 1 2). In the case of (1 2 3 4):
> (quote (1 2 3 4))
(1 2 3 4)
> '(1 2 3 4)
(1 2 3 4)
> (1 2 3 4)
Exception: attempt to apply non-procedure 1
Type (debug) to enter the debugger.
The procedure call (mem '(1 2 3 4) 1) would evaluate the expression '(1 2 3 4) before passing that value to mem. Since the expression '(1 2 3 4) evaluates to a list, that list is the value which is passed to mem. This differs from the erroneous call (mem (1 2 3 4) 1), which attempts to evaluate the expression (1 2 3 4) by calling the (nonexistent) procedure 1 with the arguments 2, 3, and 4.
You could also use list to create the input: (mem (list 1 2 3 4) 1). list is also a procedure, and so it evaluates its arguments. Here the call to mem would evaluate the expression (list 1 2 3 4), and since list is a procedure the call to list would evaluate the arguments 1, 2, 3, and 4. Numbers are self-evaluating in Scheme, so the call to list would return a list (1 2 3 4); this list is the value passed to mem, which has now evaluated its argument (list 1 2 3 4).
Some Comments on the Posted Code
The cond form can take multiple conditional clauses, and there is no reason to use if here. Instead, you can do:
(define (mem lst ele)
(cond
((null? lst) #f)
((= ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
The = predicate only works for numbers; to handle more general inputs you might choose equal?:
(define (mem lst ele)
(cond
((null? lst) #f)
((equal? ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
Now you can work with, e.g., lists of symbols, or lists of lists:
> (mem '(a b c d) 'c)
#t
> (mem '(a b c d) 'e)
#f
> (mem '(1 (2 3) 4) '(2 3))
#t
> (mem '(1 (2 (3 4)) 5) '(2 (3 4)))
#t
> (mem '(1 (2 3) 4) 3) ;; does not descend into nested lists
#f
Note that changing the equality predicate to equal? will allow lists to be searched for at the top level of the input list, but no deeper. The list (2 (3 4)) can be found in the list (1 (2 (3 4)) 5) because it is at the top level of the list, i.e., (2 (3 4)) is an element of the list (1 (2 (3 4)) 5). But, (3 4) is not an element of the top level list, so the current mem procedure can't find it here. Another definition for mem would be needed to search within nested lists.
It seems from your example that you are looking for the list '(1 4 -2) in the list '(1), which should evaluate to #f. However your implementation expects all elements to be numbers since you compare with = which is a number only comparison procedure. If you want to compare any type you should use equal? which compares two objects of any type and supports comparing structures.
You were using an acute-accent instead of a single-quote for your literals.
#lang racket
(define (mem ele lst) ;; easier to read with one element -then- list
;; ..plus that's how you wrote your call to it,
;; so this arg-order makes more sense here.
(cond ;; cond doesn't need "else"
((null? lst) #f)
((if (= ele (car lst)) #t
(mem ele (cdr lst)))) ;; element, then list now
)
)
(mem 1 '(1 4 -2))
;; don't know why element needed to be wrapped in a '(1) literal list container
;; also literals require single-quote ' character, not the ’ acute-accent
https://docs.racket-lang.org/racket-cheat/index.html
I am new at scheme and at this site.. I interrupt with this question. please give me a way to write a scheme function to calculate how many non-zero values are there in a list of numbers..
(non-zero '(4 1 0 2 0 1 3)) - 5
You have to consider three cases:
(define (non-zero numbers)
(cond ((null? numbers) 0) ; is the list empty? return zero
((not (= (car numbers) 0)) ; is the current element non-zero?
(+ 1 (non-zero (cdr numbers)))) ; add 1 to the counter and recur
(else ; otherwise
(non-zero (cdr numbers))))) ; skip to the next element
Or if your interpreter supports it, a more idiomatic solution would be to use higher-order procedures:
(define (non-zero numbers)
(count (lambda (n) (not (zero? n)))
numbers))
Either way, it works as expected:
(non-zero '(4 1 0 2 0 1 3))
=> 5
I am not familiar with scheme at all. But this can easily be implemented using recursion. Imagine a list [0,1,2,2,0,1]. You would need to walk down the list, looking at each element in turn and increasing a counter by one each time you find a 0 in the list.
(define (count_zeroes numbers)
(if (null? numbers) 0
(+ 1 (count_zeroes (cdr numbers))))
(define (search-for-primes start end)
(if (even? start)
(search-for-primes (+ start 1) end)
(cond ((< start end) (timed-prime-test start)
(search-for-primes (+ start 2) end)))))
This is part of an answer for SICP exercise 1.22 (see link at the bottom). Why is it that in the above code the guy is able to put two things after the cond condition ( (< start end) )? How does this manage to work?
If I even do (cond ((< 4 5) (< 4 3) (< 6 7))) in the terminal then that brings an error.
http://www.billthelizard.blogspot.com/2010/02/sicp-exercise-122-timed-prime-test.html
In cond, after each condition there's an implicit begin, so you can write any number of expressions afterwards, but only the value of the last one is returned as a value of that condition. In fact, your example works:
(cond ((< 4 5) (< 4 3) (< 6 7)))
=> #t
The above is equivalent to:
(cond ((< 4 5)
(begin
(< 4 3)
(< 6 7))))
What happened there? The condition (< 4 5) was evaluated to #t, then (< 4 3) was evaluated (but the value is lost, you didn't do anything with it) and finally the expression (< 6 7) was evaluated and its result returned: #t.
How would I search through the nested list to find a certain number?
For example, the list is:
((1 2) (2 3) (3 4) (3 5) (4 5))
and I'm looking for 1.
Expected output:
(1 2)
since 1 is in the sub list (1 2).
First of all create function to flatten list. Something like this:
> (flatten '((8) 4 ((7 4) 5) ((())) (((6))) 7 2 ()))
(8 4 7 4 5 6 7 2)
And then search your number in the ordinary list.
This quesion looks like the homework so try to develop this function on your own and if you can not do it - post your code here and I'll try to help you.
Updated
Ok. As I understand we need to create function which get the list of pairs and return another list of pairs, where first element of pair equal some number.
For example:
(define data '((1 2)(2 3)(3 4)(3 5)(4 5)))
(solution data 3)
-> '((3 4) (3 5))
(define data '((1 2)(2 3)(3 4)(3 5)(4 5)))
(solution data 1)
-> '((1 2))
In the other words we need to filter our list of pairs by some condition. In the Scheme there is a function to filter list. It takes a list to filter and function to decide - to include or not the element of list in the result list.
So we need to create such function:
(define (check-pair num p)
(cond
[(= (first p) num) #t]
[else #f]))
This function get a pair (element of list), number and decide - incude or not this pair to result list. This function have 2 parameters, but the filter function require the function with only one parameter, so we rewrite our function such way:
(define (check-pair num)
(lambda (p)
(cond
[(= (first p) num) #t]
[else #f])))
I have created function wich produce another function. It is currying.
So, we have all to create our solution:
(define (check-pair num)
(lambda (p)
(cond
[(= (first p) num) #t]
[else #f])))
(define (solution list num)
(local
((define check-pair-by-num (check-pair num)))
(filter check-pair-by-num list)))
(define data '((1 2)(2 3)(3 4)(3 5)(4 5)))
(solution data 1)
Flattening isn't the approach I'd prefer here, but that doesn't mean it's incorrect. Here's an alternative:
(define (solve lst num)
(cond
[(null? lst) null]
[(cons? (first lst)) (solve (first lst) num)]
[(member num lst) (cons lst (solve (rest lst) num))]
[#t (solve (rest lst) num)]))
This just recursively deals with nested listing as needed, so I prefer it a little bit stylistically. In addition, the call to member can be replaced with check-pair from above, but member will let you grab values from cdrs as well as cars, if you want that.
Use find to select a member of a list meeting a condition:
(find contains-1? '((1 2)(2 3)(3 4)(5 6)))
How to implement contains-1? Hint: consider the member function:
(member 1 '(1 2)) => #t
(member 1 '(3 4)) => #f