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.)
Related
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 have the following filter procedure:
; (2) filter
(define (filter test sequence)
; return a list of the elements that pass the predicate test
(let ((elem (if (null? sequence) nil (car sequence)))
(rest (if (null? sequence) nil (cdr sequence))))
(cond ((null? sequence) nil)
((test elem) (cons elem (filter test rest)))
(else (filter test rest)))))
And here would be an example of using it to return the even-numbered elements of a list:
(define even? (lambda (x) (= (modulo x 2) 0)))
(define sequence '(1 2 3 4 5 8 9 11 13 14 15 16 17))
(filter even? sequence)
; (2 4 8 14 16)
Is there a simple way to use the not test to invert the selection? For example, I thought the following might work:
(filter (not even?) sequence)
But it returns an error. I can define odd separately, of course:
(define odd? (lambda (x) (not (even? x))))
But I'm trying not to do this. Is there a way to write the odd procedure without defining it directly, but instead using the not directly like I'm trying to do above?
There is a complement function in Common Lisp that does what I think you are looking for. complement is a higher-order procedure that takes a procedure as its argument, and returns a procedure that takes the same arguments as the input procedure and performs the same actions, but the returned truth value is inverted.
Racket has a similar procedure, negate, and it is easy enough to implement this in Scheme:
(define (complement f)
(lambda xs (not (apply f xs))))
> (filter even? '(1 2 3 4 5))
(2 4)
> (filter (complement even?) '(1 2 3 4 5))
(1 3 5)
> (> 1 2 3 4 5)
#f
> ((complement >) 1 2 3 4 5)
#t
And in Racket:
scratch.rkt> (filter even? '(1 2 3 4 5))
'(2 4)
scratch.rkt> (filter (negate even?) '(1 2 3 4 5))
'(1 3 5)
scratch.rkt> (> 1 2 3 4 5)
#f
scratch.rkt> ((negate >) 1 2 3 4 5)
#t
The general answer to this is to simply compose not and the function you care about. Racket has a compose function which does this, but you can easily write a simple one yourself:
(define (compose-1 . functions)
;; simple-minded compose: each function other than the last must
;; take just one argument; all functions should return just one
;; value.
(define (compose-loop fns)
(cond
((null? fns)
(λ (x) x))
((null? (cdr fns))
(car fns))
(else
(λ (x) ((car fns) ((compose-loop (cdr fns)) x))))))
(compose-loop functions))
Making it efficient and more general takes more work of course.
Then you can define odd? (which is already defined of course):
(define odd? (compose-1 not even)
Or in fact define a more general CL-style complement function:
(define (complement f)
(compose-1 not f))
One option is to write an invert function which will curry things along (so the initial function still accepts one argument) until the final evaluation occurs:
(define invert (lambda (func) (lambda (x) (not (func x)))))
(define sequence '(1 2 3 4 5 6 8 9 11 13 14 15 16 17))
(filter (invert even?) sequence)
; (1 3 5 9 11 13 15 17)
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.
New to scheme here and I'm having some trouble learning do loops. I am attempting to make a function that will take in an object and a vector, and then iterate through the vector until it find that object. When the object is found, it would then return a list containing all of the items in the vector before the object. My code is below. All it will return is how many iterations the do loop went through, instead of the list I want it to. If anyone could help me with the syntax, I would greatly appreciate it. Thanks! ( ideally this would return (1 2))
(define(vector-test-iterative X Vector)
(do ((i 0 (+ i 1))) (< i (vector-length Vector))
(if (eqv? X (vector-ref Vector i))
(= i (vector-length Vector))
(cons (vector-ref Vector i) (ls '())))
ls))
(vector-test-iterative '4 #(1 2 4 3 5))
If you're using Racket, then there's no need to use do, which was never popular among schemers anyway. There's a whole range of iterators -- look for for in the docs, and things that start with for. For example, your code boils down to
#lang racket
(define (values-before x vector)
(for/list ([y (stop-before (in-vector vector)
(lambda (y) (eqv? x y)))])
y))
(If you really want to use do, then you're missing a pair of parens around the test, and you should add a binding for the accumulator.)
A solution that uses a named loop. Cleaner (in my opinion!) than the do version and should work on any R5RS Scheme:
;; Extracts the sublist of `lst` up to `val`.
;; If `val` is not found, evaluates to an empty list.
(define (upto val lst)
(let loop ((res null) (lst lst))
(cond ((null? lst) null)
((eq? val (car lst)) (reverse res))
(else (loop (cons (car lst) res) (cdr lst))))))
;; Adapts the above procedure to work with vectors.
(define (vector-upto val vec)
(list->vector (upto val (vector->list vec))))
;; test
(vector-upto 6 #(1 2 3 4 5))
=> #0()
(vector-upto 5 #(1 2 3 4 5))
=> #4(1 2 3 4)
(vector-upto 3 #(1 2 3 4 5))
=> #2(1 2)
(vector-upto 1 #(1 2 3 4 5))
=> #0()