I'm learning SICP and do the programming exercises. I have a question about exercise 4.5. The exercise 4.5 is:
Scheme allows an additional syntax for cond clauses, (<test> => <recipient>). If <test> evaluates to a true value, then <recipient> is evaluated. Its value must be a procedure of one argument; this procedure is then invoked on the value of the <test>, and the result is returned as the value of the cond expression. For example:
(cond
((assoc 'b '((a 1) (b 2))) => cadr)
(else false))
As shown above,if <test> is true,the value of the cond clause should be (<recipient> <test>) (i.e.
then <recipient> is evaluated. Its value must be a procedure of one argument; this procedure is then invoked on the value of the <test>, and the result is returned...
But when I search the solution on the Internet, almost all I found are (list (extended-cond-recipient first) (extended-cond-test first)). It's a list consist of <recipient> and <test> , not a function call.
What should I do? It has troubled me a long time...
In The Core of the Evaluator, under “Special Forms”, is written:
• A case analysis (cond) is transformed into a nest of if expressions and then evaluated.
That is, first a transformation at the program level is done, and only after this transformation the resulting expression is evaluated. The transformation is done by the function cond->if, which does not evaluate the cond expression, only transform it in a nested list containing multiple if. This can be seen in the definition of the eval function, where there is the case:
((cond? exp) (eval (cond->if exp) env))
In the solutions that you have seen, the cond->if function is modified so that it transforms the => syntax in a list (as you have correctly observed), a list that contains the function as first element, and its argument as second element, and that list will be evaluated correctly in the subsequent steps of the interpreter.
Related
I'm a beginner of the Scheme language.
Recently I found that the data type symbol can be displayed using quote, like this:
> 'E
E
> (quote E)
E
However, if the code below executed, every kind of quote may fail:
> (define 'E 123)
> 'E
E: undefined;
cannot reference an identifier before its definition
> 'abc
abc: undefined;
cannot reference an identifier before its definition
So what happend when code (define 'E 123) being executed?
First you asked Scheme to evaluate (define 'E 123). Let's put a quote in front of that, to see what it looks like without the ' shorthand. You can always do this: quote any expression to ask Scheme, "What do you think this value is?"
> '(define 'E 123)
=> (define (quote E) 123)
Well, in Scheme, (define (x ...) ...) is a shorthand for (define x (lambda (...) ...)): it's just a convenient shorthand for defining a function. So in this case (define (quote E) 123) is the same as (define quote (lambda (E) 123)). Thus, the symbol you are redefining is quote, and you define it to be a function of one parameter which always returns 123.
Next you asked to evaluate 'E. Again let's expand that to look through the shorthand:
> ''E
=> (quote E)
You now call the quote function you defined, and pass it the variable E as an argument. But E has not previously been defined, so this fails. If you wanted to, you could first define E to have any value, and then perhaps 'E would return 123. It rather depends on what Scheme evaluator you are using: the one I found does not much appreciate it when you try to redefine quote, but apparently yours does not mind, so I suspect you would get 123, and that you would get the same result if you defined abc and then evaluated 'abc.
in general (define name ...) is converted in (bind name) at the beginning of the scope and in the place where define appears, it is executed (set! name ...). You need to define a symbol, not a (quote name). Because define is a special form, the rules of evaluation are particular, not general application -- define is not a function call.
TL;DR
What I'm looking for is a combination of the functions send/apply and dynamic-send. So that it finds a method of an object based on a symbol and unpacks a list of arguments.
Background and more info
For a project I am sending some "commands" trough the network with Racket's tcp-connect. At the receivers end this command should execute a method from a class and pass along its parameters.
Consider the following received 'message':
(define message (list 'set-switch! '3 'on))
(define method-name (car msg)) ;'set-switch!
(define parameters (cdr msg)) ;(list '3 'on)
And the following class:
(define light%
(class object%
(super-new)
...
(define/public (set-switch! id mode)
(vector-set! switches id mode))))
The problem now is that when executing this statement
(dynamic-send light-class method-name parameters)
it perfectly finds the method set-switch! but it calls it with only one parameter (list '3 'on).
The Racket docs mention those three functions for classes:
(send obj-expr method-id arg) which just executes a method of an object
(send/apply obj-expr method-id arg-list-expr) which executes a method AND unpacks the argument list
(dynamic-send obj method-name v) which finds a method-name based on a symbol
What I think I need is something like (dynamic-send/apply obj method-name arg-list-expr) which combines the last two mentioned.
Note: I know that I could just simply accept lists as parameters and use car and cdr in the functions itself to get the right values. But that's not what I want.
dynamic-send is a function (also known as procedure; e.g., car, vector-set!, +), so you can use apply:
(apply dynamic-send light-class method-name parameters)
Or even simply:
(apply dynamic-send light-class message)
The reason why send has the send/apply variant is that send is a form (also known as syntax; e.g., let, define, if), so apply doesn't work and hence send/apply is separately provided.
I have been giving a language in Scheme.
(define-datatype statement statement?
(add1 (V symbol?))
(sub1 (V symbol?))
(skip (V symbol?))
(if-goto (V symbol?)
(l symbol?)))
(define-datatype instruction instruction?
(labeled (l symbol?)
(i statement?))
(unlabeled (i statement?)))
(define-datatype program program?
(a-program (l (list-of instruction?))))
I am trying to create a new function which will be able to convert the program into a list of instructions. How would I go about doing this?
Here is what I have so far:
(define pgm->list
(lambda (pgm)
;what goes here
sorry if this is wrong, if it is could you share a working implementation of your code?
i am really confused with
(define-datatype program program?
(a-program (l (list-of instruction?))))
what is list-of? i should imagine here that you want to declare some variants of programs.
a-program would be defined as a list of instructions... ok. if list-of returns a lambda that is a correct predicate (that returns true only when acted on a list of instructions) then
does this work?
(define pgm->list
(lambda (pgm)
(cases program pgm
(a-program (l) l))))
Edit : Since define-datatype was unknown to most of us except OP, i'm adding some documentation:
[syntax] (define-datatype TYPENAME [PREDICATE] VARIANT ...)
Defines a record type named TYPENAME, where VARIANT ... defines one or more
constructors for instances of this type. VARIANT should be of the form
VARIANT = (CONSTRUCTOR (FIELDNAME FIELDPRED) ...)
CONSTRUCTOR is the name of a constructor procedure that will be defined with as
many arguments as fields are specified. (FIELDNAME FIELDPRED) ... specify the name
for each field and a procedure of one argment that should return a true value for
legal field values.
The optional PREDICATE should be the name of a procedure that will be defined and
which returns #t when applied to an instance of this variant record.
[syntax] (cases TYPENAME EXP CLAUSE ...)
A facility for matching and deconstructing the instance EXP of the variant record
with the name TYPENAME. Each CLAUSE specifies a constructor with field-names and
a body to execute when the constructor matches the record instance:
CLAUSE = (CONSTRUCTOR (FIELDNAME ...) BODY ...)
| (else BODY ...)
cheers!
I have a question about Exercise 4.54 from Section 4.3.3 of Structure and Interpretation of Computer Programs (http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.3). This exercise concerns the Amb evaluator.
The exercise is the following:
If we had not realized that require could be implemented as an ordinary procedure that uses amb, to be defined by the user as part of a nondeterministic program, we would have had to implement it as a special form. This would require syntax procedures
(define (require? exp) (tagged-list? exp 'require))
(define (require-predicate exp) (cadr exp))
and a new clause in the dispatch in analyze
((require? exp) (analyze-require exp))
as well the procedure analyze-require that handles require expressions. Complete the following definition of analyze-require.
(define (analyze-require exp)
(let ((pproc (analyze (require-predicate exp))))
(lambda (env succeed fail)
(pproc env
(lambda (pred-value fail2)
(if <??>
<??>
(succeed 'ok fail2)))
fail))))
I completed it as follows:
(define (analyze-require exp)
(let ((pproc (analyze (require-predicate exp))))
(lambda (env succeed fail)
(pproc env
(lambda (pred-value fail2)
(if (false? pred-value)
(fail2) ;; or (fail)
(succeed 'ok fail2)))
fail))))
My doubt is the following:
I know that, during execution, when the predicate value pred-value is false, require should fail; that is, it should call a failure continuation procedure. But I'm a bit confused as to whether it should call (fail) or (fail2). Which one is correct?
(fail2) is the correct one. The procedure conforms to a continuation-passing style, and the correct continuation procedure in this case is fail2.
I think (fail) is correct.
Here we have got pred-value, which means pproc evaluates well for now. But if it is false value, we treat it as bad as pproc evaluates wrong. so the continuation here is fail not fail2.
A test can be found here:
https://wizardbook.wordpress.com/2011/01/22/exercise-4-54/
(fail2)is correct, well,most of the time it doesn't matter whichever you choose,but for the following conditons:
1.the predicate part contains (amb) such as
(require (amb false true false true true))
2.the predicate part contains (set! <...> <...>)
you can check it out,this is because most of the process's fail-continuation is the same as its caller's except for the above two kinds of processes. Though it sounds some kind of ridiculous.
Can anyone briefly explain to me how message passing is implemented in scheme? I think I am little off on the whole concept of message passing.
Take a look at SICP.
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-17.html#%_sec_2.4.1
http://www.michaelharrison.ws/weblog/?p=50
Message passing in the context of closures
The following example defines a closure implementing a simple calculator. The function make-calculator is similar to what object oriented languages call the constructor. The difference is: make-calculator returns a function, while constructors return object values. In object oriented languages object values are first class values. Scheme does not have such values. An object first class values provides the functionality to access object member variables and object methods. In Scheme this functionality has to be emulated by the definition of a dispatch function. make-calculator returns such a function. The body of make-calculator defines
two variables a and b (member variables)
two mutation functions set-a! and set-b! (accessors)
four evaluation functions addition, subtraction, multiplication and division (methods)
The above definitions are local to the closure make-calculator. In an object oriented language they are called private. The dispatch function makes the functions public and keeps the variables private. This works, because the dispatch function has access to the local scope of the make-calculator closure. The dispatch function accepts a message and returns the matching function. This exposes the local functions to the caller of the dispatch function.
(define (make-calculator)
(define a)
(define b)
(define (set-a! value)
(set! a value))
(define (set-b! value)
(set! b value))
(define (addition)
(+ a b))
(define (subtraction)
(- a b))
(define (multiplication)
(* a b))
(define (division)
(/ a b))
(lambda (message)
(case message
((set-a!) set-a!)
((set-b!) set-b!)
((addition) addition)
((subtraction) subtraction)
((multiplication) multiplication)
((division) division))))
First the constructor has to be called to create an "object". calc is the dispatch function, which accepts different messages, which are just symbols.
(define calc (make-calculator))
Sending a message means calling the dispatch function with a symbol argument. The following sends the message set-a! to calc, which returns the value of the local function set-a!. The name of the message and the name of the local function are the same in this case. This helps to avoid confusion, but it is not required.
(calc 'set-a!) ;; => #<procedure set-a!>
Because calc returns a function, an additional application is necessary to call the accessor. The following sets a to 3 and b to 5.
((calc 'set-a!) 3)
((calc 'set-b!) 5)
Now we can calculate:
((calc 'addition)) ;; => 8
((calc 'subtraction)) ;; => -2
((calc 'multiplication)) ;; => 15
((calc 'division)) ;; => 3/15
The code works this way in Chez Scheme.