Printing in Scheme - scheme

I am having some difficulty printing a string in scheme after using a condition and get the following error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #t
arguments...:
I can't seem to figure out what is wrong with it and would appreciate any help.
(define (neg int)
(cond
(((< int 0) (display "negative"))
(* int (-1)))))

You have too many brackets at the start of your condition; you need two, not three. Remember that in Scheme, if you surround something between () that becomes a function application! That's why this doesn't make sense: (-1), because -1 is not a function, it's a number. Also, what will you do if the value is not negative? You need to handle that case, too! Try this:
(define (neg int)
(cond ((< int 0)
(display "negative ")
(* int -1)) ; or better: (- int)
(else
(display "positive ")
int)))

Related

Error during macro expansion: Empty body #f

I'm learning Scheme and I can't figure out what I did wrong with this code:
(define (distance a b)
(define c 1)
(define loop
(lambda (a b c)
((if (<= c b)
(begin
(display (c (* a c)))
(newline)
(apply loop '(a b (+ c 1))))
'done)))))
I'm trying to make a program that takes in speed and hours, then displays the distance traveled for each hour on a separate line. When I run the code in an interpreter, I get an empty body error:
Error during macro expansion: Empty body #f
I'm running the code with the Larceny interpreter.
edit:
I rewrote the code to call the inside function loop from the body of the distance function and the code works perfectly. Updated code:
(define (distance a b)
(define c 1)
(define (loop x y z)
(if (<= z y)
(begin
(display "Hour: ")
(display z)
(display " Speed: ")
(display x)
(display " Distance: ")
(display (* x z))
(newline)
(loop x y (+ z 1)))
'done))
(loop a b c))
There seems to be a missing body. In Scheme a lambda is defined as
(lambda (args ...)
(define local-binding ...) ...
body ...)
In distance c and loop are local defines, but there is no body. Thus distance doesn't do anything with a or b and if it worked it would always return an undefined value. eg. not a very useful procedure.
When you'e fixed that you might want to have a look at My code signals the error “application: not a procedure” or “call to non procedure”

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 to write to stdout within a conditional expression in MIT-Scheme?

Here is an example of an attempt to write a different string to stdout depending on the value of a variable:
(let ((x 1))
(cond ((< x 2)
(display "hooray"))
(else
(display "bummer")))
)
Notice that the correct string does get written, but we also get an "Unspecified return value"
My understanding is that this happens because the interpreter is trying to return the value of the "consequent expression" of the clause as the value of the conditional, but the "display" expression does not return any value.
Is there a better way of doing this?
Given that this expression is evaluated only for its effect (printing a message), you should explicitly return a value (any value!) as the result of the let form:
(let ((x 1))
(cond ((< x 2)
(display "hooray")
(newline))
(else
(display "bummer")
(newline)))
'ok)
Now we'll get:
hooray
'ok

DrRacket define begin set! probably should work but dont

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))

Scheme: cannot use #t in an if statement

Apologies if the question title is a bit confusing. Maybe after you are through reading it, you can suggest me a better title.
As a part of a homework assignment for an online course, I wrote an iterative procedure in mit-scheme to display number from 1 to a given number.
The code below works fine:
(define (count2-iter num)
(define (iter counter)
(cond ((> counter num) #t)
(else (display counter)
(iter (+ counter 1)))))
(iter 1))
The output:
1 ]=> (load "count2-iter.scm")
;Loading "count2-iter.scm"... done
;Value: count2-iter
1 ]=> (count2-iter 10)
12345678910
;Value: #t
Personally I do not like using cond for 2 branches only and I tried to use if for this.
(define (count2-iter1 num)
(define (loop idx)
(if (> idx num)
#t
((display idx)
(loop (+ idx 1)))))
(loop 1))
The output:
1 ]=> (count2-iter1 5)
5
;The object #!unspecific is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
Why is this? Shouldn't #t be evaluated the same way it was used in cond? Would really appreciate an explanation as I am still new to Scheme.
Try this instead:
(define (count2-iter1 num)
(define (loop idx)
(if (> idx num)
#t
(begin ; notice the difference!
(display idx)
(loop (+ idx 1)))))
(loop 1))
Here's why: when you use an if, there can be only one expression in the consequent part and one in the alternative part. If more than one expression is needed, we have to surround them with a (begin ...). You surrounded the expressions between (...), which is not ok, because parenthesis are used for function application (that's why the error message states that The object #!unspecific is not applicable).
On the other hand, a cond has an implicit begin for each of its clauses when a condition is met. Personally, I prefer to stick with using cond when I need more than one expression after a condition - it's less verbose.

Resources