Why am I getting a #<undef> is not a function error? - scheme

This is my code and I am slightly confused why I am receiving this error. My code is just to find the roots for a quadratic equation.
(define (roots a b c)
(define det
(- (* b b) (* 4 a c))
)
(if (> det 0) (
(display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
(display (/ (- (* b -1) (sqrt det)) (* 2 a)))
)
)
(if (= det 0) (
(display (/ (* b -1) (* 2 a)))
(display (/ (* b -1) (* 2 a)))
)
)
(if (< det 0) (
(display "complex roots")
(display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
(display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
)
)
)
(roots -2 4 5)
(roots -2 4 -5)

I believe you meant to add a begin in the body of your one armed if's. The display procedure has a void return value, and the extra parentheses will try to apply the value as a procedure. You can reproduce the error by running ((display 5)). Using begin will allow you to instead evaluate the expressions in sequence.
This code will display the values without any exceptions:
(define (roots a b c)
(define det
(- (* b b) (* 4 a c))
)
(if (> det 0) (begin
(display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
(display (/ (- (* b -1) (sqrt det)) (* 2 a)))
)
)
(if (= det 0) (begin
(display (/ (* b -1) (* 2 a)))
(display (/ (* b -1) (* 2 a)))
)
)
(if (< det 0) (begin
(display "complex roots")
(display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
(display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
)
)
)

The parentheses in Scheme are very special. They mean apply:
(define (test arg) arg)
((test +) 4 5) ; ==> 9
The same in JavaScript:
const plus = (a, b) => a+b; // Needed since + is not a function in JS
const test = arg => arg
test(plus)(4,5) // ==> 9
In your code you have:
((display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
(display (/ (- (* b -1) (sqrt det)) (* 2 a))))
Unfortunately the expression in operator position return #<undef>. Actually accoring to the spec it can return anything because its undefined in the specification. Ib your particular implementation though it's not a function so it's like:
((test 'symbol) 4 5); ==> Error: symbol is not a function
As you saw earlier having a call to test did work earlier so expressions in operator position is perfectly valid code and almost impossible to reason about at compile time, but in runtime it will become obvious it's not possible to continue when apply gets a non function.
Now there are macros that use parentheses for something else than application and these you just have to know or read the documentation for. An example is cond
(cond ((= 3 5) #t)
(else #f))
; ==> #f
If you've never seen cond before it's easy to assume ((= 3 5) #t) is an expression and of course by looking at it it shouldn't work since (= 3 5) would not evaluate to a function object but a boolean. However each term in cond evaluates it's car then each element in the rest of the term in order if it happened to be a true value.
To do more expressions in order and return the value of the last expression one uses begin:
(begin 1 2 3)
; ==> 3
Here evaluating 1 and 2 is clearly dead code since it doesn't do anything. Thus its inherit that using begin implies a side effect where the return value is of not importance, but the side effect is. I don't think your function really needs side effects:
(define (roots a b c)
(define det
(- (* b b) (* 4 a c)))
(cond ((> det 0)
(list (/ (+ (* b -1) (sqrt det)) (* 2 a))
(/ (- (* b -1) (sqrt det)) (* 2 a))))
((= det 0)
(list (/ (* b -1) (* 2 a))))
((< det 0)
(list (/ (+ (* b -1) (make-rectangular 0 (sqrt (* det -1)))) (* 2 a))
(/ (- (* b -1) (make-rectangular 0 (sqrt (* det -1)))) (* 2 a))))))
(roots -1 4 -4) ; ==> (2 -2)
(roots 1 0 -4) ; ==> (2)
(roots 4 0 4) ; ==> (0+1i 0-1i)

Related

Printing decimal numbers get rounded up in chicken-scheme

I have a scheme procedure that returns 0.24999999999999992 as a result. However, when I tried to print this result with chicken-scheme on my machine, it gets rounded to 0.25. How can I prevent rounding?
I tried running the same procedure on repl.it, and the print command here outputs the result without rounding.
If it helps, the code below:
(define (sum term a next b)
(if
(> a b)
0
(+ (term a) (sum term (next a) next b))
)
)
(define (integral-simpson f a b n)
(define h (/ (- b a) n))
(define (inc x) (+ x 1))
(define (term x)
(cond
((or (= x 0) (= x n)) (f (+ a (* x h))))
((even? x) (* 2 (f (+ a (* x h)))))
((odd? x) (* 4 (f (+ a (* x h)))))
)
)
(* (/ h 3)
(sum
term
a
inc
n
)
)
)
(define (cube x)
(* x x x)
)
(print (integral-simpson cube 0 1 100))
Try changing the print precision: (flonum-print-precision 17)

Why doesn't my counter work with the function "alternate"?

I have to make a function "alternate" which return another function depending of the number of time "alternate" is called.
I first try a simple counter with the square function and it worked well.
(define square
(let ((a 0))
(lambda (x)
(begin
(set! a (+ a 1))
(writeln a)
(* x x)))))
(map square '(1 2 3 4))
It returns as expected
1
2
3
4
'(1 4 9 16)
I want my program below to display
1
2
3
4
'(2 1 6 2)
But I don't know why it seems the counter stays to one. So my program display
1
'(2 4 6 8)
(define alternate
(let ((a 0))
(lambda (f g selector)
(begin
(set! a (+ a 1))
(writeln a)
(if (selector a)
(lambda (x) (f x))
(lambda (x) (g x)))))))
(map (alternate (lambda (x) (* x 2))
(lambda (x) (/ x 2))
odd?)
(first-n-integers 4))
Ps: (first-n-integers 4) return a list
'(1 2 3 4)
The problem is that alternate is executing exactly once and returning a single lambda as its result - instead of that you want to apply it every time. This should work:
(define (alternate f g selector)
(let ((a 0))
(lambda (x)
(set! a (+ a 1))
(writeln a)
(if (selector a)
(f x)
(g x)))))
For example:
(map (alternate (lambda (x) (* x 2))
(lambda (x) (/ x 2))
odd?)
(first-n-integers 4))
1
2
3
4
'(2 1 6 2)

DrRacket/Scheme: not a procedure

I am trying to create program in Scheme (DrRacket) to solve roots of quadratic equation. I have also function to solve discriminant (function D). If discriminant is >0 function root should have on the output "point pair" (is that the correct word? english is not my native language) of both roots. Else it should give #f on the output.
(define na2
(lambda (x)
(* x x)))
(define D
(lambda (a b c)
(- (na2 b) (* 4 a c))))
(define roots
(lambda (a b c)
((if (> (D a b c) 0)
(cons (/ (+ (- b) (sqrt (D a b c))) (* 2 a)) (/ (- (- b) (sqrt (D a b c))) (* 2 a)))
#f)))
It gives me this:
> (roots 1 3 2)
>: contract violation
expected: real?
given: (-1 . -2)
argument position: 1st
other arguments...:
>
As you can see the correct output is there, but why the error?
Edit:
I corrected typo, as Parakram Majumdar helepd me, now it gives me
application: not a procedure;
expected a procedure that can be applied to arguments
given: (-1 . -2)
arguments...: [none]
Can someone please tell what am I doing wrong?
As discussed in the comments, the if statement should be written as follows:
(if cond then else)
where the condition would be :
(> (D a b c) 0)
So overall it should be:
(define roots
(lambda (a b c)
(if (> (D a b c) 0)
(cons (/ (+ (- b) (sqrt (D a b c))) (* 2 a))
(/ (- (- b) (sqrt (D a b c))) (* 2 a)))
#f
)))

Scheme quadratic function/square root check

Im want to make a function where rootcheck has a list L as input, L always is 3 atoms (a b c) where a is coefficient of x^2, b coef of x and c is the constant. it checks if the equation is quadratic, using discriminant (b^2 - 4ac) and should output this (num 'L) where num is the number of roots and L is a list that contains the roots themselves (using quadratic formula), L is empty in case of no roots. here is my code:
(define roots-2
(lambda (L)
(let ((d (- (* (cdr L) (cdr L)) (4 (car L) (caddr L))))))
(cond ((< d 0) (cons(0 null)))
((= d 0) (cons(1 null)))
(else((> d 0) (cons(2 null)))))
))
its giving me no expression in body error.
also I tried to code the quadratic function and even tried some that are online, one compiled fint but gave me an error when I inserted input this is the code for the quadratic function, NOT MINE!
(define quadratic-solutions
(lambda (a b c) (list (root1 a b c) (root2 a b c))))
(define root1
(lambda (a b c) (/ (+ (- b) (sqrt (discriminant a b c)))
(* 2 a))))
(define root2
(lambda (a b c) (/ (- (- b) (sqrt (discriminant a b c)))
(*2 a))))
(define discriminant
(lambda (a b c) (- (square b) (* 4 (* a c)))))
There are several mistakes in the code:
Some parentheses are incorrectly placed, use a good IDE to detect such problems. This is causing the error reported, the let doesn't have a body
You forgot to multiply in the 4ac part
You're incorrectly accessing the second element in the list
The else part must not have a condition
The output list is not correctly constructed
This should fix the errors, now replace null with the actual call to the function that calculates the roots for the second and third cases (the (< d 0) case is fine as it is):
(define roots-2
(lambda (L)
(let ((d (- (* (cadr L) (cadr L)) (* 4 (car L) (caddr L)))))
(cond ((< d 0) (list 0 null))
((= d 0) (list 1 null))
(else (list 2 null))))))
for the quadractic function part, I found a code online and tweaked it to provide both roots of a quadratic equation. returns a list of both roots
(define (solve-quadratic-equation a b c)
(define disc (sqrt (- (* b b)
(* 4.0 a c))))
(list (/ (+ (- b) disc) (* 2.0 a))
(/ (- (- b) disc) (* 2.0 a))
))

Normal order vs Applicative order in Scheme

I got this program:
(define a 2)
(define (goo x)
(display x) (newline)
(lambda (y) (/ x y)))
(define (foo x)
(let ((f (goo a)))
(if (= x 0)
x
(f x))))
and I asked to compare the evaluation results between the applicative and normal order on the expression (foo (foo 0)).
As I know, in applicative order, (display x) in function goo will print x and after it the program will collapse because y isn't defined. But when I run it in Scheme nothing happens. What is the reason?
(foo 0) evaluates to this code:
(define (goo 2)
(display 2) (newline)
(lambda (y) (/ 2 y)))
(define (foo x)
(let ((f (goo 2)))
(if (= 0 0)
0
((lambda (y) (/ 2 y)) 0))))
and prints 2, returning 0. While (foo 4) evaluates to:
(define (goo 2)
(display 2) (newline)
(lambda (y) (/ 2 y)))
(define (foo 4)
(let ((f (goo 2)))
(if (= 4 0)
4
((lambda (y) (/ 2 y)) 4))))
and prints 2, returning 0.5.

Resources