4 Lab ... and Yet More Syntax
Goals |
— |
— |
— |
Exercise 6. Develop the macro where, which is a kind of backward let that has an expression followed by a binding that can be used by the expression. The binding is evaluated before the expression (even though it appears later). For example,
(where (+ my-favorite-number 2) [my-favorite-number 8]) produces 10.After you have where with a single binding working, generalize it to support multiple bindings. With that generalization,produces 100.Now implement where*, which is a backwards let* that evaluates its clauses and binds in reverse order:
Exercise 7. Develop the macro and/v, which is like and except that it binds the result of its first expression to a variable written => identifier. For example,evaluates to 2, butevaluates to #f. You can use #:literals in syntax-parse, since => is already bound (assuming you think that binding’s reuse is appropriate).After getting and/v to work, make the => identifier part optional. Note that both => and identifier must be both omitted or both present.
Exercise 8. Modify the definition of split-ct from lecture so that it can also deal with specifications that do not provide literal constants for start and end. When a non-literal start or end is provided, the rage check should happen at run time.
Here is the code from lecture:
#lang racket (require (for-syntax syntax/parse)) (begin-for-syntax (define-syntax-class byte (pattern b:nat #:fail-unless (< (syntax-e #'b) 256) "not a byte"))) ; SYNTAX ; (split-ct tags start end [name:id step (~optional convert)] ...) ; computes the values of the fields name... by successively extracting ; bytes from tags, beginning at start to maximally end (define-syntax (split-ct stx) (syntax-parse stx [(_ tags start:integer end:byte [name step:byte (~optional convert)] ...) ; — — — — — — — — — — — ; the static error checking #:do [(define end-int (syntax-e #'end)) (define step-int (sum #'(step ...)))] #:fail-unless (< step-int end-int) "index out of range" ; — — — — — — — — — — — #`(let ([i start]) (let*-values ([(i name) (values (+ i step) (extract tags i (+ i step -1)))] ...) (values ((~? convert values) name) ...)))])) ; [Listof [Syntax Number]] -> Number ; compute the sum of the numbers hidden in syntax (define-for-syntax (sum list-of-syntax-numbers) (apply + (map syntax-e (syntax->list list-of-syntax-numbers)))) Start by copying and pasting this code into your DrRacket.
Exercise 9. Start with the code from lecture and add the following pre-defined, arity-checked functions:
plus, which takes two number arguments and adds them;
minus, which takes two number arguments and adds them; and
string+, which takes two srting arguments and concatenates them.
Add these without using define-function.For example, (function-app plus 1 2) should produce 3, but your implementation should not include (define-function (plus x y) ***).
These primitives must work with the protocol from lecture. If you fancy adding other pre-defined function, please feel free to do so.
Expression = .... | (++ Expression) A (++ Expression) form produces a number 1 larger than the value of Expression.
Exercise 11. Develop a macro that consumes an identifier x and generates a definition for x that initializes it to how many such definitions (including the one for x) have been created so far in the whole program. For example, if your macro is called define-as-next, then
(define-as-next x) (define-as-next y) (define-as-next z) defines x as 1, y as 2, and z as 3.When you have a solution, try this:
(define-as-next x) (define (get-y) (define-as-next y) y) (define one-y (get-y)) (define another-y (get-y)) What values do x, one-y, and another-y get? Explain. Try adding (define-as-next z) to the end again and check the value of z.Next, encapsulate the definition of the compile time function in a module named server and the uses of the function in a module called client. Your Definitions window will look like this:
#lang racket (module server racket (provide define-as-next) *** (define-syntax (define-as-next stx) ***)) (module client racket (require (submod ".." server)) ***) Does your solution still work? If not, fix it.Now duplicate client, use client2 for the second one. Run your program. What do you see? Explain.
Please fill out today’s post-day survey.