Quiz 3: Syntactic Abstraction
Instructions
- The quiz consists of five questions.
- Read through all the questions before you begin. It is worth your time to plan ahead.
- The quiz is worth 60 points. Each question is worth twelve points.
-
Write your answers in the space provided on the exam.
You may write on the back of a page if you need more space. - Partial credit will be given where possible, so show your work.
- The quiz lasts forty-five (45) minutes. It is due at 1:45 PM.
Problem 1
Give brief answers to each of these questions about syntactic abstraction. One sentence each should be sufficient for the first and second bullets — two sentences each max.
- What is the benefit of the syntactic abstractions in a language for the users of the language?
- What is the benefit of the syntactic abstractions in a language for the implementers of the language?
-
For each of these language features, list the core feature it is
a syntactic abstraction of.
-
selection operators such as
cond
andcase
- functions that take more than one argument
- variable references
-
selection operators such as
Problem 2
Write a structurally recursive function
(or->if or-exp)
, where
or-exp
is described by this grammar:
<or-exp> ::= (or . <arglist>) <arglist> ::= '() | (<symbol> . <arglist>)
or->if
returns an equivalent if
expression. For example:
> (or->if '(or)) ; or is false with no arguments #f > (or->if '(or x y)) '(if x #t (if y #t #f)) > (or->if '(or a b c d e)) '(if a #t (if b #t (if c #t (if d #t (if e #t #f)))))
Hint: Make or->if
an interface procedure that
strips the symbol 'or
from the front of its argument
and calls a helper function on the list of symbols.
Problem 3
Answer these questions about local variables as a syntactic abstraction.
-
Translate this Racket expression into its semantically
equivalent core form that binds a value to the variable's
name.
(let ((line-item (* unit-cost number-of-units))) (* line-item (add1 sales-tax-rate)))
-
Explain why Racket's special form
letrec
is necessary. That is, explain why we cannot uselet
to create a local recursive procedure. (One or two sentences should be enough here.) - For a quick two points: King Kong or Godzilla?
Problem 4
Answer each of these questions about lexical addresses.
-
Write the lexical address for each variable reference, in the
form
(v : d p)
.(lambda (f) (lambda (m n) (f (* m m) (sub1 n)))) (lambda (x y) ( (lambda (y z) (x y z)) y))
-
Give equivalent Racket expressions for these expressions
in lexical address form, or explain why there is no such
expression.
(lambda 2 (lambda 3 (((: 1 1) (: 0 0)) ((: 0 1) (: 1 0) (: 0 2))))) (lambda (a b c) (lambda (d e) (((: 1 0) (: 1 2)) (: 0 2))))
Problem 5
On Homework 7, we added a let
expression to our
little language.
Add a case to the definition of
lexical-address-helper
so that it can handle
let
expressions.
See the language details on the next page.
((let? exp) ; a new case for let
expressions
; FILL-IN-THE-BLANK
)
The Little Language for Problem 5
Problem 5 uses the little language we worked with on our lexical
addressing exercise in Sessions 19-20, extended with a
let
expression.
<exp> ::= <varref> | (lambda (<var>*) <exp>) | (<exp> . <exp>*) | (if <exp> <exp> <exp>) | (let (<var> <exp>) <exp>) <--- new from Homework 7
Like a Racket let
expression, this let
expression creates a new block declaring an identifier. The
region of the local variable is the body of the let
expression. References to a local variable within the body of
the let
are at a depth of 0. For example:
> (lexical-address '(let a = x in (f a a))) '(let a = (x : 0 0) in ((f : 1 1) (a : 0 0) (a : 0 0))) > (lexical-address '(let a = g in (let b = y in (f a b)))) '(let a = (g : 0 0) in (let b = (y : 1 1) in ((f : 2 2) (a : 1 0) (b : 0 0))))
Use the syntax procedures for let
expressions to
write your code:
let? make-let let->var let->val let->body
The Existing Code for lexical-address-helper
(define (lexical-address-helper exp list-of-decls) (cond ((varref? exp) (lexical-address-for exp list-of-decls 0)) ((if? exp) (make-if (lexical-address-helper (if->test exp) list-of-decls) (lexical-address-helper (if->then exp) list-of-decls) (lexical-address-helper (if->else exp) list-of-decls))) ((app? exp) (make-app (lexical-address-helper (app->proc exp) list-of-decls) (map (lambda (e) (lexical-address-helper e list-of-decls)) (app->args exp)))) ((lambda? exp) (make-lambda (lambda->params exp) (lexical-address-helper (lambda->body exp) (cons (lambda->params exp) list-of-decls)))) (else (error 'lexical-address "unknown exp ~a" exp) )))