(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.
Related
I'm running a Scheme program and getting an error when I run this code with s = (1 2 3 4 5), saying SchemeError: pair is not callable: (1 2 3 4 5). I know what this error means in Python, but I'm not sure how it applies to Scheme.
This is my program.
(define (ordered? s)
(define (helper val lastVal newS)
(if (null? cdr(newS))
(val)
(if (<= lastVal car(newS))
(helper #t car(newS) cdr(newS))
(helper #f car(newS) cdr(newS))
)
)
)
(helper #t 0 s)
)
So I figured it out. I was using the car and cdr procedures wrong, so I was getting extra parenthesis around my list.
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 want to use "do" command to show(1 1)(1 2)(1 3)(2 1)(2 2)(2 3)(3 1)(3 2)(3 3)
and my code is below:
(lambda ( )
(define a 1)
(define b 1)
(do ((a 1 (+ a 1))) (= a 3)
(do ((b 1 (+ b 1))) (= b 3)
(display a b)
)))
But this only show3as the result. Did I do something wrong? How should I correct it?
To Michael Vehrs,
Thank a lot, it really works! But I'm still confusing about the exit condition. I tried to change the>in your code to=and it shows(1 1)(1 2)(2 1)(2 2). Is it because it stops when a = 3 so it won't print?
So "list" command can combine several variables. But how about "newline" command? I tried to remove it and it just add another () in the last.
Thank you for the answer. I'm a new Scheme learner trying to use it on TracePro. Do you have any tip(book, Youtube video, website) for me about learning Scheme? Any advise would help.
A do loop is just syntax sugar for a recursive function. You might as well get used to write it directly. Here is a way to do it with one named let with two variables and an accumulator.
(let loop ((a 3) (b 3) (acc '()))
(cond ((zero? a) acc) ; finished
((zero? b) (loop (sub1 a) 3 acc)) ; b finsihed, reduce a and reset b
(else (loop a (sub1 b) (cons (list a b) acc))))) ; reduce b and add to front of acc
; ==> ((1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3))
Notice this makes the result in reverse order so it's optimal for lists that always are created in reverse order since that only can add new element in front.
You mean:
(lambda ()
(do ((a 1 (+ a 1)))
((> a 3) (newline))
(do ((b 1 (+ b 1)))
((> b 3))
(display (list a b))))))
Your code has a number of problems: The exit condition for the do loop is incorrect (and makes your procedure return 3). display takes a single object and an optional port as arguments. Defining your variables a and b is unnecessary, since the do construct defines new loop variables anyway.
I was reading the SICP and encountered with a problem, in chapter 1 there is an example named counting change, I need to write a program in scheme to calculate the possible number of ways to make a change of any given number given half-dollars, quarters, dimes, nickles and pennies.
the book shows a substitution model of program and I tried to change it to a nesting one but failed, could anyone give me a favor?
(define (count_change total_amount)
(define (denomination kinds_of_coins)
(cond ((= kinds_of_coins 5) 50)
((= kinds_of_coins 4) 25)
((= kinds_of_coins 3) 10)
((= kinds_of_coins 2) 5)
((= kinds_of_coins 1) 1)))
(define (cc amount kinds_of_coins)
(cond (= amount 0) 1)
((or (< amount 0) (= kinds_of_coins 0)) 0)
(else (+ (cc amount (- kinds_of_coins 1))
(cc (- amount (denomination kinds_of_coins)) kinds_of_coins))))
(cc total_amount 5))
the execution result is as follows:
;Ill-formed clause: 1
A cond expression generally takes the form (cond (predicate expr) ... (else expr)) or (cond (predicate expr) ... (#t expr)). Whenever a predicate evaluates to true, the correspondent expression in the clause is the result of the conditional expression. If you do not have an else/#t predicate at the end and all of the predicates on the conditional expression are false, generally the expression returns a void value.
Here, you have a syntax error because you did not started a clause properly. So, instead of having (cond (= amount 0) 1) you should have (cond ((= amount 0) 1) ...).
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()