How do i write an if else statement in this code?
I am new to AI and we are learning about if/else statements. I am unsure about how to write the else statement. I continuously get errors.
(define (nextmove location status)
(if (eq? status 'dirty) 'suck 'no\idea))
SO here ^^^ i have to write an if/else statement to print out the following
> (nextmove 'A 'dirty)
'suck
> (nextmove 'B 'clean)
'left
However, it is printing out
<(nextmove 'B 'clean)
'noidea
#lang racket
(define (nextmove location status)
(cond
[(eq? status 'dirty) 'suck]
[(eq? status 'clean) 'left]
[else 'noidea]))
Conditionals: if, cond, and, and or
Related
I'm trying to print a list of pairs of values (representing key/value pairs) in Racket.
Here's the code I have right now:
#lang racket
(define (write-json keyvalues)
(displayln "{")
(for-each
(lambda (kv) (
(displayln (format "~a: ~a," (car kv) (cdr kv)))))
keyvalues)
(displayln "}"))
(write-json (list (cons "a" 1) (cons "b" 2)))
When I run the example, it prints:
{
a: 1,
Then, it crashes with this error message:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...: [none]
context...:
/.../racket/collects/racket/private/map.rkt:58:19: loop
"test.rkt": [running body]
for-loop
run-module-instance!125
perform-require!78
Any idea what's going on?
Thanks!
This is a paren issue. You have an extra set of parentheses around your lambda's body, ie:
( (displayln (format "~a: ~a;" (car kv) (cdr kv))) )
Since displayln is used for side effect, its output is void, hence why your error message states that you're trying to run (#<void>).
In general, whenever you get an error stating "expected a procedure that can be applied to arguments", see if you have parentheses issues in your code block. Editors like Dr. Racket would highlight that region for you.
I have the following Racket code:
#lang racket
(define (for-each proc items)
(cond ((not (null? items))
(proc (car items))
(for-each proc (cdr items)))))
(for-each (lambda (x) (newline) (display x))
(list 57 321 88))
Because the condition isn't satisfied after 88 is printed, and the Racket's documentation says:
If none of the question-expressions evaluates to true, cond’s value is the answer-expression of the else clause. If there is no else, cond reports an error.
So the expected result is an error, however I get the correct output:
57
321
88
Can somebody tell me why? (ps: I'm using DrRacket 6.2)
Changing the indentation a little:
(define (for-each proc items)
(cond
[(not (null? items)) (proc (car items))
(for-each proc (cdr items))]))
A call (for-each f (list 1 2 3))
will call the function and bind proc to f and items to '(1 2 3).
The test (not (null? items)) is true, since '(1 2 3) is non-empty.
The right hand side is therefore evaluated. The right hand side does two things:
1.) (proc (car items)) calls f with the first element in the list (here 1) and then 2). calls (for-each proc (cdr items)). Here (cdr items) becomes '(2 3).
Eventually for-each will be called with (for-each f '()).
At that point (not (null? items)) will evaluate to #f and the cond will try the next clause. Since there are no more clauses cond will return void.
The documentation says:
If no cond-clauses are present, the result is #<void>.
Note: The cond in the teaching languages will return an error. The constructs in the teaching language generally reports errors, where there is a chance of shooting ones own foot.
I don't know where you got that information. To quote the spec:
The last test-expr in a cond can be replaced by else. In terms of evaluation, else serves as a synonym for #t, but it clarifies that the last clause is meant to catch all remaining cases. If else is not used, then it is possible that no test-exprs produce a true value; in that case, the result of the cond expression is #void.
I am trying to create a macro for while loop in DrRacket. Here is what I wrote:
(require mzlib/defmacro)
(define-macro my-while
(lambda (condition body)
(list 'local (list (list 'define (list 'while-loop)
(list 'if condition
(list body (list 'while-loop))
'(void))))
'(while-loop))))
(define x 0)
(my-while (< x 10)
(begin
(display x)
(newline)
(set! x (+ x 1))))
The output of this program is:
0
1
2
3
4
5
6
7
8
9
error: procedure application: expected procedure, given: #<void>; arguments were: #<void>
Can someone help me with this? Why wouldn't this macro just terminate and return void. It seems that when the condition is not true, the system tries to apply the void as an argument to some procedure.
Ouch:
Using this style of while loop encourages excessive use of imperative programming.
Using define-macro creates unhygienic macros, which is a nightmare in Scheme.
While I don't encourage writing an imperative-style loop macro, for your reference, here's a non-define-macro version of the same macro:
(define-syntax-rule (my-while condition body ...)
(let loop ()
(when condition
body ...
(loop))))
It uses syntax-rules, which creates hygienic macros, and is much, much easier to read than what you have.
Now, for the actual answer for your question, first, let's write your original macro out in a more readable way:
(define-macro my-while
(lambda (condition body)
`(local ((define (while-loop)
(if ,condition
(,body (while-loop))
(void))))
(while-loop))))
Once you write it out this way, you can see where the real problem is: in the (,body (while-loop)) line, which should instead have been (begin ,body (while-loop)).
Why use a macro when a plain old function will do?
;; fun-while : (-> Boolean) (-> Any) -> Void
(define (fun-while condition body)
(when (condition)
(body)
(fun-while condition body))
Of course, this requires you to pass in repeatable actions that can be called (this is why condition and body are surrounded with parens in the body of fun-while), so you do need a macro if you want prettier syntax. But once you have a function that has the desired behavior, putting some sugar on top is trivial for this case:
(define-syntax-rule (my-while condition body ...)
(fun-while (lambda () condition)
(lambda () body ...)))
Now, as has been said, this encourages imperative style, which is frowned upon. Instead of mutation, try making the state explicit instead:
;; pure-while : forall State.
;; (State -> Boolean) ; the "condition" that inspects the state
;; (State -> State) ; the "body" that moves from one state to the next
;; -> ; curried
;; State ; the current state
;; -> State ; produces the ending state
(define ((pure-while condition make-next) current-state)
(if (condition current-state)
(pure-while condition make-next (make-next current-state))
current-state))
You'll notice that the first two arguments are now functions from State to something, and the result of applying to 2 arguments is also a function from State -> State. This is a recurring pattern that, as a Haskeller, I'd call the "State Monad". Discussion of putting sugar on top of this concept is a little beyond the scope of this conversation, though, so I'll just stop there.
Another version of while uses a do loop:
(define-syntax while
(syntax-rules ()
((while pred? stmt ...)
(do () ((not pred?))
stmt ...))))
Because it's been a while:
a while macro for Racket 6.0
#lang racket
(define-syntax while
(syntax-rules ()
((_ pred? stmt ...)
(do () ((not pred?))
stmt ...))))
I am writing a program which needs communication between processes.
my code:
#lang racket
(define-values (sp o i e) (subprocess #f #f #f "c://player1.exe" ))
(define count 10)
(for ([c (in-naturals)])
(cond
[(equal? count 0) (error "Province is empty!") ]
[else
(write "server" i)
(set! count (sub1 count))
(flush-output i)
(display (read o))]))
and the player1.exe code:
#lang racket
(define (interact notification)
(cond
[(eq? notification "server") (write "true" (current-output-port))]
[else (write "false" (current-output-port))]))
(for ([c (in-naturals)])
(interact (read (current-input-port)))
(write "player" (current-output-port))
(sleep 0.1)
flush-output (current-output-port))
I am getting output if I run without loops. I am also getting output when only player is sending messages. But with both server and player sending messages the program gets hanged.
What do you think the problem is?
The last line in your player1.exe file looks suspicious. flush-output is not actually being applied as a function. Rather than
flush-output (current-output-port)
you probably mean:
(flush-output (current-output-port))
From a style point of view: the functions read, write, and flush-output all work on the current input and output ports by default, so you don't need to provide them. Take a look at the documentation for those functions, such as flush-output, and you'll see that it mentions that the current-output-port is its default.
So the line that we just looked at can be written as:
(flush-output)
More issues: don't use eq? to compare strings. Use string=? instead. The reason is that there can be two strings that have the same textual content, but for which eq? will still be able to distinguish the two. e.g.:
kui $ racket
Welcome to Racket v5.2.1.
> (eq? "a" (string-copy "a"))
#f
> (string=? "a" (string-copy "a"))
#t
This is my function:
(defun MyFunction(input)
(let ((NEWNUM (find input num)))
(if (find input num) //if this
(setq num NEWNUM) (FUNCT2) //then execute both of these
(list 'not found)))) //else output this
So after the if statement I want to be able to execute (setq num NEWNUM) followed by (FUNCT2) in order to set a new variable and then call a function. Any ideas on how to do this?
To do several things in sequence, you want progn.
(defun MyFunction(input)
(let ((NEWNUM (find input num)))
(if (find input num) //if this
(progn
(setq num NEWNUM)
(FUNCT2)) //then execute both of these
(list 'not found)))) //else output this
When your if is 'one-armed', as they call it (that is, it contains no else branch), it's typically easier and more idiomatic to use when and unless: http://www.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/mac_whencm_unless.html
When you call (when pred x y ... z), it will just evaluate x y z sequentially if pred is true. unless behaves similarly when pred is NIL. x y z can represent any number of statements from one upwards. Thus:
(when pred (thunk))
is just the same as
(if pred (thunk))
Some people say when and unless should always be used for 'one-armed-ifs' because of clarity.
Edit: Your thread gave me an idea. This macro:
(defmacro if/seq (cond then else)
`(if ,cond (progn ,#then) (progn ,#else)))
should enable this:
(if/seq (find input num) //if this
((setq num NEWNUM) (FUNCT2)) //then execute both of these
((list 'not found)))))
So the general format is:
(if/seq *condition* (x y ... z) (a b ... c))
Depending on the condition, it evaluates all of the subforms in the first or second, but only returns the last.
You can't use multiple statements with if, except with progn as posted above. But there is the cond form,
(cond
((find input num) // if this
(setq num NEWNUM) // then execute both of these
(FUNCT2))
(t
(list 'not found))) // else output this
Just to add, you could also use the (begin exp1 exp2...) syntax to evaluate more than one expression in Lisp sequentially. Using this on an if's branch will have the same effect as using multiple statements.