DrRacket define begin set! probably should work but dont - scheme

Im learning for exam of programming in lisp using DrRacket..
In presentation from lectures i found this code:
(define (f a b c)
(define delta)
(begin
(set! delta (- (* b b) (* 4 a c))
(if (>=? delta 0)
(writeln ”są pierwiastki”)
(writeln ”nie ma pierwiastków)))))
But it dont work.
DrRacket is showing:
. define: bad syntax (missing expression after identifier) in: (define delta)
Can't I set delta value later?
What is the problem?
thanks in advance

The original error message is because
(define delta)
is missing a value. Instead it should be something like:
(define delta 0)
There some other issues:
The double quotes weren't the " character and weren't recognized
by Racket.
Some parens were wrong.
Also I don't know why it was define-ing delta, then immediately
set!-ing it.
I tried to fix/simplify what you posted, and came up with the
following. But I'm not really sure what the function is supposed to
do, so I don't know if the example output is correct.
#lang racket
(define (f a b c)
(define delta (- (* b b) (* 4 a c)))
(if (>= delta 0)
(displayln "są pierwiastki")
(displayln "nie ma pierwiastków")))
;; Example output:
(f 1 2 3)
;;-> nie ma pierwiastków
(f 1 200 3)
;;-> są pierwiastki

Try this:
#lang racket
(define (f a b c)
(define delta 0)
(set! delta (- (* b b) (* 4 a c)))
(if (>= delta 0)
(displayln "są pierwiastki")
(displayln "nie ma pierwiastków")))
What was wrong with your code:
It's probably a copy-paste error, but in Scheme we delimit strings using the " character, not ” as in your code. And the last line is missing the closing ".
Although some interpreters accept a define without an initial value, the standard is that a value must be present after the variable name
A closing parenthesis is missing at the end of the set! line
The define and set! lines can be merged into a single line: (define delta (- (* b b) (* 4 a c)))
The >=? operator is not standard in Scheme, it might work in your interpreter but if possible use the standard >=
The writeln procedure is not standard in Scheme, in Racket you can substitute it for displayln
Not really an error, but you don't need to write a begin inside a procedure definition, it's implicit
In conclusion: the code in the question seems to be intended for a different interpreter, this question was tagged racket but believe me, what you have is not valid Racket code - heck, is not even standard Scheme. Make sure to use the correct interpreter, and be very alert for typos in the text.

I think Greg already has a perfect answer to your problem, but I just want to add the obvious let version of his code as well:
;; for a given ax^2+bx+c=0
;; this displays if it has at least one
;; real number answer or not
(define (equation-has-answer a b c)
(let ((delta (- (* b b) (* 4 a c))))
(if (>= delta 0)
(displayln "Has answer(s)")
(displayln "Has no answers"))))
To just make a predicate you can do this:
;; for a given ax^2+bx+c=0
;; this returns #t if it has at least one
;; real number answer and #f otherwise
(define (equation-has-answer? a b c)
(>= (- (* b b) (* 4 a c)) 0))

Related

Scheme: Proabably a typo in SICP. 1.3.2. Am I right?

In SICP, (1.3.2. page: 62), there is a solution for finding pi-sum using lambda. The solution is:
(define (pi-sum a b)
(sum (lambda (x) (/ 1.0 (* x (+ x 2))))
a
(lambda (x) (+ x 4))
b))
However, I feel there should be a bracket enclosing ((lambda (x) (+ x 4) b). The program as such produces an error saying sum is expecting a number but getting a procedure.
Modifying the above code is giving no error.
(define (pi-sum a b)
(sum ((lambda (x) (/ 1.0 (* x (+ x 2))))
a)
((lambda (x) (+ x 4))
b)))
Please correct me if my understanding is wrong. I assume the book cannot be wrong.
The pi-sum procedure in the book is making use of the higher-order procedure sum, defined earlier in 1.3.1. The sum procedure takes a and b as arguments which describe the bounds of the summation, and it takes term and next as arguments which describe how to create a term from a, and how to get the next a from the current a. Both term and next need to be procedures. Here is the definition of sum from the book:
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
If you add parentheses in the definition of pi-sum, you should get an exception because sum requires four arguments, but now only two are passed. I am not sure why you are getting an error like "sum is expecting a number but getting a procedure", but I suspect that you have a different definition for sum than the one intended by the book.

How to use typed scheme/racket

I am trying to learn typed scheme/racket(?). Down below I have an example from my code:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
I would like to implement a procedure "check" which checks if two datatypes are allowed with an operator. For example,
(check '(+ int int))
Should result in
int
But
(check '(* int (+ real int)))
Should result in something like this:
The operator '+' must have two operands of the same (numerical) type.
That is, check should take a list.
Questions:
How do I implement "check"? Firstly I though "ok, I have a list, so let's use car and cdr" to get the operator and the operands but it didn't work and I don't even know why it doesn't work. I also though about making if statements like (if (and (= x y) (or (= x int) (= y int)) and so on to make the checks but... don't think this is the right way to go.
Should I make a procedure "add" or not? Is there any other way to do this? Int the examples it looks like they are only using "+", "-" and so on. Lastly; How do I check that the input "int" is an int and then gives int as output.
I am pretty lost right now and I am sorry for my pretty vaugue questions but I would be really happy if someone could help me out to understand this.
Note: the procedure add takes real numbers and output a real number so it doesn't follow along with the example too well. But I hope you grasp the idea. Thanks :)
You're asking a fascinating question, and it doesn't have a simple answer.
The program that you're trying to write is essentially a type-checker. That is, it takes an expression, and checks to see whether the given function's domain includes the arguments it's being called with. We can write one of those, but I suspect you're going to be unsatisfied. Here, let me go write one now....
#lang typed/racket
(require typed/rackunit)
;; a type is either
;; - 'number, or
;; - (list 'fn list-of-types type)
;; examples of types
'number
'(fn (number number) number)
(define-type FnTy (List 'fn (Listof Ty) Ty))
(define-type Ty (U 'number FnTy))
;; given an expression, returns a type
;; or signals an error
(: check (Any -> Ty))
(define (check input)
(cond [(and (list? input)
(pair? input)
(symbol? (car input)))
(define fn-ty (lookup-fn-type (car input)))
(define arg-types (map check (rest input)))
(cond [(equal? (cadr fn-ty) arg-types)
(caddr fn-ty)]
[else (error 'check
"expression didn't type-check: ~v\n"
input)])]
[(number? input)
'number]
[else (raise-argument-error
'check
"well-formed expression"
0 input)]))
(: lookup-fn-type (Symbol -> FnTy))
(define (lookup-fn-type fn-name)
(match fn-name
['+ '(fn (number number) number)]
[other (raise-argument-error 'lookup-fn-type
"known function name"
0 fn-name)]))
(define TEST-INPUT '(+ 3 43))
(check-equal? (check TEST-INPUT)
'number)
(check-equal? (check '(+ (+ 3 4) 129837))
'number)
Does this answer any part of your question?

How do I print my procedure call in Scheme?

I am trying to convert a C program to Scheme for an assignment I'm working on. The program is supposed to compute the area of a circle given the formal parameter (diameter, in this case). I think I have it figured out but I don't know how to print the actual value to verify it. I've tried just putting in the number into the print call. The way it is now is the method my book used. When I run the program with Dr. Racket I get:
print: undefined;
cannot reference undefined identifier
(define pi 3.14159265)
(define test 5)
(define (areac d)
(lambda (d)
(* pi (/ d 2) (/ d 2)
)))
(print (areac test))
Edit: Language is set to R5RS
If you use "define", you don't have to use "lambda", because "define" is just convenient way to give the name to the lambda-procedure. Your code must look like this:
(define pi 3.14159265)
(define test 5)
(define (areac d)
(* pi (/ d 2) (/ d 2)
))
(display (areac test))
Command for printing data in scgeme is "display". So, just write
(display (areac test))

Error: Can't bind name in null syntactic environment

I'm currently going through exercise 1.3 of the sicp book. Here's the description of the problem:
Define a procedure that takes three numbers as arguments and returns
the sum of the squares of the two larger numbers.
I tried to solve it with the following code
(define (square x) (* x x))
(define (sq2largest a b c)
((define large1 (if (> a b) a b))
(define small (if (= large1 a) b a))
(define large2 (if (> c small) c small))
(+ (square large1) (square large2))))
When I ran it in mit-scheme, I got the following error:
;Can't bind name in null syntactic environment: large1
#[reserved-name-item 13]
Googling this error doesn't yield many results. Does anyone know what's wrong with my code? (I'm not familiar with Scheme)
I'll try to break down the structure of your sq2largest procedure:
The basic structure is:
(define (sq2largest a b c)
; Body)
The Body you wrote is:
((define large1 (if (> a b) a b)) ; let this be alpha
(define small (if (= large1 a) b a)) ; let this be bravo
(define large2 (if (> c small) c small)) ; let this be charlie
(+ (square large1) (square large2)) ; let this be delta) ; This parentheses encloses body
So, the Body is structured as:
(alpha bravo charlie delta)
Which translates to: "Pass bravo, charlie and delta as arguments to alpha."
Now, alpha is being told to take a bunch of arguments, but inside the namespace reserved for large1, no provision was made for any argument... i.e. scheme encounters a null syntactic environment where it cannot bind any variable.
Parentheses are significant in Scheme (and most, if not all, Lisps) because they define the scope of a procedure and enforce[1] the order of application of operations.
[1] "No ambiguity can arise, because the operator is always the leftmost element and the entire combination is delimited by the parentheses." http://mitpress.mit.edu/sicp/full-text/sicp/book/node6.html
You have too many brackets. If you took out the extra brackets around the internal defines, things should work a lot better.

What am I doing wrong with Scheme?

When I enter the following:
(define (root a b c)
(/ (+ (-b) (sqrt (- (exp b 2) (* 4 a c)))) (* 2 a)))
and then enter:
(root 3 6 2)
I get a message indicating that the procedure had two arguments but only requires exactly one. What am I doing wrong?
The exp function doesn't do exponents really, it does something else mathy. (I don't know.)
What you want is usually called pow for "power" but probably isn't defined in your environment, so I suggest you just define your own square method:
(define (square x) (* x x))
And then:
(define (root a b c)
(/ (+ (- b) (sqrt (- (square b) (* 4 a c)))) (* 2 a)))
Edit: Oh, you'll also have to change a couple spacing issues, like (* 4 a c) instead of (*4 a c), and (- b) instead of (-b). You always have to separate the operator from the operands with spaces.
The procedure exp raises the number e to the power of its argument, if you need to raise an argument to the power of another argument, use expt. Even better, given that you only need to square b, a simple multiplication will do. Like this:
(define (root a b c)
(/ (+ (- b) (sqrt (- (* b b) (* 4 a c))))
(* 2 a)))
The function the error refers to is exp which takes only one argument. The exp function calculates the exponential function, not an exponent. You want expt, which raises a root x to the exponent y:
(expt b 2)
You can also just multiply the number times itself.
I usually keep R5RS or The Scheme Programming Language on hand since these basic functions can be hard to keep straight.

Resources