Issues with conditionals in Scheme - scheme

I'm using Scheme with the full Swindle package, and I'm trying to use conditionals to recursively determine evenness/oddity of integers. My code is as follows:
(define (odd? x)(
(cond
((= x 0) '#f)
((= x 1) '#t)
((= (even? (- x 1)) #t) '#f)
(else '#t))))
(define (even? x)(
(cond
((= x 0) '#f)
((= x 2) '#t)
((= (odd? (- x 1)) #t) '#f)
(else '#t))))
However, when I run (even? x) or (odd? x) [x is some number, doesn't matter what, as I get the same error] I get: application: not a procedure;
expected a procedure that can be applied to arguments
given: #t
arguments...: [none]
Can anyone help? Thanks. I'm not 100% familiar with ideal Scheme syntax, so it might be that.

You have an erroneous pair of parentheses surrounding the cond expression (that's causing the error reported). But also, there are way too many conditions in each procedure, and because you're using = to compare numbers with boolean values, there will be a point where a contract violation will occur. For fixing that you can replace = with equal? in here:
((equal? (even? (- x 1)) #t) '#f)
And in here:
((equal? (odd? (- x 1)) #t) '#f)
But then, the procedures will still give an incorrect result:
(even? 5)
=> #t
(odd? 7)
=> #f
Honestly, I think it'd better to simplify the implementation, that will solve all the problems. Try this instead:
(define (odd? x)
(cond ((= x 0) #f)
(else (even? (- x 1)))))
(define (even? x)
(cond ((= x 0) #t)
(else (odd? (- x 1)))))
Now we'll get correct answers:
(even? 4)
=> #t
(even? 5)
=> #f
(odd? 6)
=> #f
(odd? 7)
=> #t

Any Scheme form in parentheses is an application, like (sin 42) or (42 sin). The first calls sin as a function with argument 42 and produces a value; the second tries to call 42 with an argument sin, but 42 is no procedure, so this causes an error. Similarly (42) is an application with no arguments; still it must have a procedure to be applied as its first part, to be called with no arguments, right? In Scheme, parentheses matter, they are not just for grouping stuff (as they may be in some other languages). So the extra parentheses cause an extra attempt to evaluate the result, which is a Boolean, i.e. not a procedure, so this is an error.
Then, '#f is just #f; similarly for #t (they both evaluate to themselves); and a condition (= test #t)1 (equal? test #t) is the same as just test (produces the same set of Boolean results) ((1 we can't use = to compare Booleans, it is supposed to be used with numbers only)):
(define (odd? x)
(cond
((= x 0) #f)
((= x 1) #t)
((even? (- x 1)) #f)
(else #t)))
Also, (if test #f else...) is the same as (if (not test) else... #f):
(define (odd? x)
(cond
((= x 0) #f)
((= x 1) #t)
((not (even? (- x 1))) #t)
(else #f))) ; (else ...) is like (#t ...)
using logical connectives, the clauses with the same outcome can be merged, and mutually exclusive clauses can be rearranged (mutual exclusivity can be achieved with explicit guards):
(define (odd? x)
(cond
((and (/= x 0) ; a guard
(or (= x 1)
(not (even? (- x 1))))) #t)
((or (= x 0) #t) #f)))
but (cond (test #t) (else #f) is (if test #t #f) which is just test:
(define (odd? x) (and (> x 0) ; `>` is better
(or (= x 1)
(not (even? (- x 1))))))
The guard (> x 0) prevents the fall-through for negative xes.
But then, this is completely wrong. For n to be odd, n-1 must be even, not the opposite!
(define (odd? x) (and (> x 0) ; work only for positive integers
(or (= x 1)
(even? (- x 1)))))
We could write (not (odd? (- x 1))), but then it wouldn't be tail recursive. It would be tail recursive modulo cons (not serving as a "constructor"), but for some historic fluke of a reason2, TRMC optimization isn't required of a Scheme implementation. The last expression in and and or forms is, in fact, in tail position. But not in not. ((2 despite being described as early as 1974.))
Repeat the same for your definition of even?.

Related

Scheme Inverting values

I'm trying to convert #t to #f, #f to #t and a negative number to a positive and the opposite.
(define inverse
(lambda (x)
(cond ((eq? x #t) #f)
((eq? x #f) #t)
(else - x))))
It works for the boolean but not the number.
(else - x) is not a valid form. Change it to (else (- x)).
Btw, you can go without cond:
(define (inverse x) (if (boolean? x) (not x) (- x)))

Scheme R5RS contract violation

The code below is the answer given by the professor for a question in my intro to scheme course but it comes out with an error. Cannot see why.
#!r5rs
(define (make-complex a b) (cons a b))
(define (real x) (car x))
(define (imag x) (cdr x))
(define (complex-sqrt x)
(define (sgn v)
(cond ((< v 0) -1)
((= v 0) 0)
(else 1)))
(let ((root (sqrt (+ (* (real x) (real x))
(* (imag x) (imag x))))))
(make-complex (sqrt (/ (+ (real x) root) 2))
(* (sgn (imag x))
(sqrt (/ (- root (real x)) 2))))))
(complex-sqrt 7)
;; ERROR mcar: contract violation
;; expected: mpair?
;; given: 7
I took a screenshot of the error with trace illustartion while running it in DrRacket.
Here's your code transcribed. Please consider posting the actual code rather than a screenshot in future.
(define (make-complex a b) (cons a b))
(define (real x) (car x))
(define (imag x) (cdr x))
(define (complex-sqrt x)
(define (sgn v)
(cond ((< v 0) -1)
((= v 0) 0)
(else 1)))
(let ((root (sqrt (+ (* (real x) (real x))
(* (imag x) (imag x))))))
(make-complex (sqrt (/ (+ (real x) root) 2))
(* (sgn (imag x))
(sqrt (/ (- root (real x)) 2))))))
Was the (complex-sqrt 7) part provided by your professor too? We're trying to get the square root of a complex number, so we should pass in a complex number:
(complex-sqrt (make-complex 5 2))
'(2.27872385417085 . 0.43884211690225433)
Which according to https://www.wolframalpha.com/input/?i=sqrt(2i%2B5) is correct!
The implementation of complex-sqrt is an unsafe one. What that means is that it assumes you pass it a complex number, in this case something created with make-complex.
To fix this you need to check if the argument is complex:
;; Not 100%. Should use `struct` to not
;; mix with random pairs that happens to have numeric parts
(define (complex? x)
(and (pair? x)
(number? (car x))
(number? (cdr x))))
;; The original code is renamed to unsafe-complex-sqrt
(define (complex-sqrt x)
(if (complex? x)
(unsafe-complex-sqrt x)
(raise-argument-error 'complex-sqrt "complex?" x)))
Now you can test it:
(complex-sqrt (make-complex 7 0))
; ==> (2.6457513110645907 . 0)
(complex-sqrt 7)
; ERROR complex-sqrt: contract violation
; expected: complex?
; given: 7
Perfect. Now it says you have mot passed the required complex number to a function that requires a complex number to work.
So what happend in the original code?
In unsafe-complex-sqrt it uses car and cdr which are safe operations that signal contract violation if the argument x supplied isn't #t for (pair? x).
Racket uses mcons in its #!r5rs implementation and thus the errors refer to every pair/list function in R5RS prefixed with an m since the error doesn't pay attention to renaming.

How to write scheme cond so it returns the value of a nested cond

I have a function that basically goes
(cond
(
(cond)
(cond)
)
)
At the moment scheme seems like a foreign language to me. My question is simple. How do I get the first cond to return true only if the nested have also returned true. From what I've gathered the nested (cond)(cond) is being treated as the test for the first right? All I keep getting is #void for a return.
Like this:
(cond ((cond ((= 1 2) #f)
((= 2 3) #f)
(else #f))
#t)
((cond ((= 3 4) #f)
((= 4 5) #f)
(else #t)) ; this is the only #t condition
#t)) ; hence this #t value is returned
In the above example, only the last else in the second inner cond returns true, which in turns returns true in the condition of the outermost cond.
But really, why would you want to do such a thing? if you have multiple conditions, just use different branches of a single cond. Maybe you're misunderstanding how it's supposed to be used? think of it as a series of if-else if-else if-else statements in other programming languages.
There is no reason to do that. Imagine this example:
(cond ((cond ((< x 10) #t)
((> x 20) #t)
(else #f))
#t)
((cond ((< y 10) #t)
((> y 20) #t)
(else #f))
#t))
This can easily be flattended down to one cond:
(cond ((< x 10) #t)
((> x 20) #t)
((< y 10) #t)
((> y 20) #t)
(else #f))
You could use or to take the first true value. This works for all true values, not just #t (Everything not #f is considered true)
(or (cond ((< x 10) 'small-x)
((> x 20) 'big-x)
(else #f))
(cond ((< y 10) 'small-y)
((> y 20) 'big-y)
(else #f)))
Even if you can use cond for every conditional its probably wise to only use it where there are either side effects involved or there are more than one predicate (like elseif in Algol languages) and use if as the conditional for one predicate. Eg. you can write one of the sub-conds above to this:
(cond ((>= 20 x 10) #f)
(else #t))
Now I would automatically have changed from cond to if since it's no longer nessecary for a cond:
(if (>= 20 x 10)
#f
#t)
Perhaps a bad example since the whole if can be written (not (>= 20 x 10)).

Scheme prime numbers

this is possibly much of an elementary question, but I'm having trouble with a procedure I have to write in Scheme. The procedure should return all the prime numbers less or equal to N (N is from input).
(define (isPrimeHelper x k)
(if (= x k) #t
(if (= (remainder x k) 0) #f
(isPrimeHelper x (+ k 1)))))
(define ( isPrime x )
(cond
(( = x 1 ) #t)
(( = x 2 ) #t)
( else (isPrimeHelper x 2 ) )))
(define (printPrimesUpTo n)
(define result '())
(define (helper x)
(if (= x (+ 1 n)) result
(if (isPrime x) (cons x result) ))
( helper (+ x 1)))
( helper 1 ))
My check for prime works, however the function printPrimesUpTo seem to loop forever. Basically the idea is to check whether a number is prime and put it in a result list.
Thanks :)
You have several things wrong, and your code is very non-idiomatic. First, the number 1 is not prime; in fact, is it neither prime nor composite. Second, the result variable isn't doing what you think it is. Third, your use of if is incorrect everywhere it appears; if is an expression, not a statement as in some other programming languages. And, as a matter of style, closing parentheses are stacked at the end of the line, and don't occupy a line of their own. You need to talk with your professor or teaching assistant to clear up some basic misconceptions about Scheme.
The best algorithm to find the primes less than n is the Sieve of Eratosthenes, invented about twenty-two centuries ago by a Greek mathematician who invented the leap day and a system of latitude and longitude, accurately measured the circumference of the Earth and the distance from Earth to Sun, and was chief librarian of Ptolemy's library at Alexandria. Here is a simple version of his algorithm:
(define (primes n)
(let ((bits (make-vector (+ n 1) #t)))
(let loop ((p 2) (ps '()))
(cond ((< n p) (reverse ps))
((vector-ref bits p)
(do ((i (+ p p) (+ i p))) ((< n i))
(vector-set! bits i #f))
(loop (+ p 1) (cons p ps)))
(else (loop (+ p 1) ps))))))
Called as (primes 50), that returns the list (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47). It is much faster than testing numbers for primality by trial division, as you are attempting to do. If you must, here is a proper primality checker:
(define (prime? n)
(let loop ((d 2))
(cond ((< n (* d d)) #t)
((zero? (modulo n d)) #f)
(else (loop (+ d 1))))))
Improvements are possible for both algorithms. If you are interested, I modestly recommend this essay on my blog.
First, it is good style to express nested structure by indentation, so it is visually apparent; and also to put each of if's clauses, the consequent and the alternative, on its own line:
(define (isPrimeHelper x k)
(if (= x k)
#t ; consequent
(if (= (remainder x k) 0) ; alternative
;; ^^ indentation
#f ; consequent
(isPrimeHelper x (+ k 1))))) ; alternative
(define (printPrimesUpTo n)
(define result '())
(define (helper x)
(if (= x (+ 1 n))
result ; consequent
(if (isPrime x) ; alternative
(cons x result) )) ; no alternative!
;; ^^ indentation
( helper (+ x 1)))
( helper 1 ))
Now it is plainly seen that the last thing that your helper function does is to call itself with an incremented x value, always. There's no stopping conditions, i.e. this is an infinite loop.
Another thing is, calling (cons x result) does not alter result's value in any way. For that, you need to set it, like so: (set! result (cons x result)). You also need to put this expression in a begin group, as it is evaluated not for its value, but for its side-effect:
(define (helper x)
(if (= x (+ 1 n))
result
(begin
(if (isPrime x)
(set! result (cons x result)) ) ; no alternative!
(helper (+ x 1)) )))
Usually, the explicit use of set! is considered bad style. One standard way to express loops is as tail-recursive code using named let, usually with the canonical name "loop" (but it can be any name whatever):
(define (primesUpTo n)
(let loop ((x n)
(result '()))
(cond
((<= x 1) result) ; return the result
((isPrime x)
(loop (- x 1) (cons x result))) ; alter the result being built
(else (loop (- x 1) result))))) ; go on with the same result
which, in presence of tail-call optimization, is actually equivalent to the previous version.
The (if) expression in your (helper) function is not the tail expression of the function, and so is not returned, but control will always continue to (helper (+ x 1)) and recurse.
The more efficient prime?(from Sedgewick's "Algorithms"):
(define (prime? n)
(define (F n i) "helper"
(cond ((< n (* i i)) #t)
((zero? (remainder n i)) #f)
(else
(F n (+ i 1)))))
"primality test"
(cond ((< n 2) #f)
(else
(F n 2))))
You can do this much more nicely. I reformated your code:
(define (prime? x)
(define (prime-helper x k)
(cond ((= x k) #t)
((= (remainder x k) 0) #f)
(else
(prime-helper x (+ k 1)))))
(cond ((= x 1) #f)
((= x 2) #t)
(else
(prime-helper x 2))))
(define (primes-up-to n)
(define (helper x)
(cond ((= x 0) '())
((prime? x)
(cons x (helper (- x 1))))
(else
(helper (- x 1)))))
(reverse
(helper n)))
scheme#(guile-user)> (primes-up-to 20)
$1 = (2 3 5 7 11 13 17 19)
Please don’t write Scheme like C or Java – and have a look at these style rules for languages of the lisp-family for the sake of readability: Do not use camel-case, do not put parentheses on own lines, mark predicates with ?, take care of correct indentation, do not put additional whitespace within parentheses.

Translation of Scheme code for Sierpinski carpet

I found code for generating Sierpinski carpet at http://rosettacode.org/wiki/Sierpinski_carpet#Scheme - but it won't run in the DrRacket environment or WeScheme. Could someone provide solutions for either environments?
It looks like this code runs fine in DrRacket after prepending a
#lang racket
line indicating that the code is written in Racket. I can provide more detail if this is not sufficient.
I've translated the program to run under WeScheme. I've made a few changes: rather than use (display) and (newline), I use the image primitives that WeScheme provides to make a slightly nicer picture. You can view the running program and its source code. For convenience, I also include the source here:
;; Sierpenski carpet.
;; http://rosettacode.org/wiki/Sierpinski_carpet#Scheme
(define SQUARE (square 10 "solid" "red"))
(define SPACE (square 10 "solid" "white"))
(define (carpet n)
(local [(define (in-carpet? x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))]
(letrec ([outer (lambda (i)
(cond
[(< i (expt 3 n))
(local ([define a-row
(letrec ([inner
(lambda (j)
(cond [(< j (expt 3 n))
(cons (if (in-carpet? i j)
SQUARE
SPACE)
(inner (add1 j)))]
[else
empty]))])
(inner 0))])
(cons (apply beside a-row)
(outer (add1 i))))]
[else
empty]))])
(apply above (outer 0)))))
(carpet 3)
Here is the modified code for WeScheme. WeScheme don't support do-loop syntax, so I use unfold from srfi-1 instead
(define (unfold p f g seed)
(if (p seed) '()
(cons (f seed)
(unfold p f g (g seed)))))
(define (1- n) (- n 1))
(define (carpet n)
(letrec ((in-carpet?
(lambda (x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))))
(let ((result
(unfold negative?
(lambda (i)
(unfold negative?
(lambda (j) (in-carpet? i j))
1-
(1- (expt 3 n))))
1-
(1- (expt 3 n)))))
(for-each (lambda (line)
(begin
(for-each (lambda (char) (display (if char #\# #\space))) line)
(newline)))
result))))

Resources