Error with the following code - scheme

When I do (visit-doctor suppertime) for this code:
(define (visit-doctor name)
(if (equal? name 'suppertime) (end-session)
((write-line (list 'hello name))
(write-line '(what seems to be the trouble?))
(doctor-driver-loop name initial-earlier-response))))
(define (end-session) (write-line '(the doctor is done seeing patients today)))
it gives me this error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #
arguments...:
#
#

Your problem is that you're trying to use brackets for grouping a block of code.
Scheme doesn't do that.
Your else branch is
((write-line (list 'hello name))
(write-line '(what seems to be the trouble?))
(doctor-driver-loop name initial-earlier-response))
which is a list of three elements.
The first element of that list is expected to a procedure, which is then applied to the other two elements, but when you evaluate (write-line (list 'hello name)) you don't get a procedure, you get #<void>.
The fix is to sequence it using begin:
(begin (write-line (list 'hello name))
(write-line '(what seems to be the trouble?))
(doctor-driver-loop name initial-earlier-response))

Related

Evaluating code which refers to function parameters

Update: The original version of this question did not fully describe the constraints of my situation. It now includes an example with some hand-waving for the sake of simplicity as well as a testable minimum example.
I am trying to pass a snippet of code into a procedure for evaluation at a later point in time. The system with all of the constraints looks like this:
; External Library code - cannot be changed
(define (serialize-parameters . args)
(format some-file "~A~%" args))
(define (function-called-later-possibly-after-a-system-reboot callback)
(apply callback some-default-parameters (deserialize-parameters some-file)))
; Internal library code - can be changed, but the value of `code-snippet` cannot be hardcoded
(define (callback some-default-parameters code-snippet)
(eval code-snippet (current-module))
; Application code - can be changed, can be hardcoded
(define (main)
(serialize-parameters #:code-snippet '(format #t "~A~%" some-default-parameters)))
The main point is to allow the application to execute an arbitrary code snippet in a callback function. The callback function receives other parameters which are not known to the application and may change between calls.
An important constraint is that the parameters that the application wants to send to the callback are written to a file and then read back at a later point in time, possibly after a system reboot.
This example is easier to test, but does not capture all of the constraints:
(define (test foo bar)
(eval bar (current-module)))
(test "value of foo" '(format #t "~A~%" foo))
Running this program results in Unbound variable: foo. What I want is for the test function to be defined in such a way that the result of the call will be "value of foo\n" being printed to the terminal. Is this possible in Guile?
Thank you.
This will no work. eval takes an environment and you pass it (current-module). That are top level bindings in the module, like test but not any lexical bindings like foo or bar. They just don't exist in the environment returned by (current-module).
You can do this:
(define foo "value of foo")
(eval '(format #t "~A~%" foo) (current-module))
; prints "value of foo"
; ==> #t
Also, the elephant in the room is that you can do this with lambdas:
(define (test value proc)
(proc value))
(test "value to process" (lambda (foo) (format #t "~A~%" foo)))
; prints "value to process"
; ==> #t
Alternatively, but I'm guessing you can't have format in callback because "code-snippet" can have many different values:
(define (main)
(serialize-parameters #:code-snippet "~A~%"))
(define (callback some-default-parameters code-snippet)
(format #t code-snippet some-default-parameters))
EDIT
I think you can do it semi hard-coded:
(define (main)
(serialize-parameters #:code-snippet 'print-format))
(define (callback argument message)
(case message
((print-format) (format #t "~A~%" argument))
((other-message) (handle-message ...))
(else ...)))
You can even make it a dynamic dispatcher. Eg. you do something like this:
(define messages '())
(define (register-callback message proc)
(set! messages (cons (cons message proc) messages)))
(define (callback argument message)
(let ((found (assq message messages)))
(when found
((cdr found) argument))))
(register-callback 'print-format (lambda (arg) (format #t "~A~%" arg)))
(callback "test" 'print-format) ; prints "test"
Now only the message gets stored in a file, which easily can be any data literal.

Understanding block structure in MIT Scheme

Take the following function definition as my example:
(define (foo)
(bar)
(define (bar)
(display "bar")))
This would produce an error: ;Premature reference to reserved name: bar. On the contrary, the following two definitions are legitimate. Note that I'm using premature reference in both of them.
(define (foo)
(bar))
(define (bar)
(display "bar"))
(define (foo)
(define (bar)
(display "bar"))
(bar))
My question is: why can't I prematurely reference a currently undefined function when using block structure? And why is bar a "reserved name"?
You can reference it, but you can't use what's still undefined.
Racket lets you define
(define (foo)
(bar) ; here the future error
(define (bar)
(display "bar"))
(bar))
but when you try to call (foo) it errors with the message
bar: undefined;
cannot use before initialization
So, there is a certain timeline involved here, certain sequencing; some things are done before others, according to their textual position in the definition. Consider this further Racket REPL interaction:
> (define (foo) (baz) (define (bar) (display "bar")) (bar))
> (foo)
. . baz: undefined;
cannot reference an identifier before its definition
> (define (baz) '())
> (foo)
bar
The REPL has its own timeline. Each Scheme implementation can handle this aspect of REPL in its own way, though.

Temporary Variable Assistance (Scheme)

I'm making a random sentence generator using Scheme (Pretty Big), and I'm having trouble defining temporary variables. I want to make something like this:
<NOUN1> <VERB1> <NOUN2> <but> <NOUN2> <VERB1> <NOUN2> <also>
Example: Sharks eat fish, but fish eat fish also.
I have word lists, and functions to choose a word from said list. Then, I use append to create a function. I am able to do:
(define (sentence)
(append (getNoun) '(and) (getNoun) (getVerb)))
However, I am unable to figure out a way to temporarily define a variable.
I have this so far:
(define (sentence1)
(append (getNoun)
(lambda (verb getVerb)
(noun getNoun))
(verb) (noun) '(but) (noun) (verb) (noun)))
Hints/Help please?
You are looking for let.
http://docs.racket-lang.org/reference/let.html
Here is an example usage:
(define (my-proc age)
(let ([age-plus-10 (+ age 10)])
(printf "age is ~a" age)
(printf "age-plus-10 is ~a" age-plus-10)))
Notice how we can temporarily define age-plus-10 and then use it later.

Simple interpreter in Scheme

I will describe my problem on example.
I'll get (play '(left nothing right left)). Some of the names in the list are real procedures, others i want to skip.
(define (left)
'left
)
I need to interpret procedures with names in the list. What is the solution?
When I try ( (car '(left nothing right left))) I get error : procedure application: expected procedure, given: left (no arguments)
(car '(left nothing right left)) evaluates to the symbol left, which is the name of a procedure, but not actually a procedure, so you can't call it.
You'll want to build an association list mapping symbols to procedures:
(define actions `((left . ,(lambda () 'left))
(right . ,(lambda () 'right))
(nothing . ,(lambda () (display "I'm staying put")))))
then you can call the appropriate function for the first element in your list as
((cdr (assoc (car '(left nothing right left)) actions)))
You can also use quasiquoting to construct a list containing a mixture of symbols you want evaluated and others you don't, e.g.
(play `(,left nothing nothing ,right nothing))
left and right will expand to whatever you've defined them as (such as a procedure) while nothing is not un-quoted so it will be left as a symbol. play would then have to test each member to see if it's a procedure, something like:
(define (play xs)(for-each (lambda (x)(if (procedure? x)(x) x)) xs))

How to ignore side-effect in Racket from using `set!`?

In Exercise 35.4.2 from HtDP, I've implemented the GUI and have a button called "Remove" which invokes a callback function. Here it is:
(define (cb-remove x)
((lambda (name result)
(cond
[(number? result) (remove-name name address-book)]
[else (draw-message msg "Not found")]))
(string->symbol (text-contents label-name))
(lookup (string->symbol (text-contents label-name)) address-book)))
When I run this, I get the following message: button-callback: result of type <Boolean> expected, your function produced #<set!-result>. The problem is that I have to call set! in order to change the address book. However, the result of set! is (void), which cannot cannot be combined with a Boolean type. How can I avert this problem? Thanks for any insight.
Simple:
(begin (set! foo bar) #t)

Resources