Consider how adding an excess of macros can make code harder to read
and debug. Which of the following is the *least* compelling reason to
implement a macro?

- Eliminate syntactic repetition and its associated bugs
- Optimize memory use by reducing function calls
- Set up a specialized control flow, eg, one that doesn’t evaluate arguments left to right
- Build a form with a different binding structure

Recall the PICKY language we went over in class last week. Which one
of these statements about the type judgements/rules of our PICKY
language is *not* true?

- In the
`+`

rule: to prove`{+ A B}`

has type`Number`

, we need to prove`A`

has type`Number`

and`B`

has type`Number`

- In the
`call`

rule: to prove`{call F V}`

has type`τ₂`

, we need to prove`F`

has type`(τ₁ -> τ₂)`

and`V`

has type`τ₁`

- In the
`fun`

rule: to prove`{fun {x : τ₁} : τ₂ E}`

has type`(τ₁ -> τ₂)`

, we need to prove`x`

has type`τ₁`

and`E`

has type`τ₂`

- In the
`if`

rule: to prove`{if C T E}`

has type`τ`

, we need to prove that`C`

has type`Boolean`

,`T`

has type`τ`

, and`E`

has type`τ`

Which of these is *not* a valid reason to use a type system?

- Make code more organized
- Better documentation of code
- Make programs run faster
- Check the correctness of a program’s execution
- Find errors in unexecuted code
- Reduce debugging time

Consider the evaluation rules for the PICKY language:

eval(N,env) = N

eval(x,env) = lookup(x,env)

eval({+ E1 E2},env) = eval(E1,env) + eval(E2,env)

...

eval({fun {x} E},env) = <{fun {x} E}, env>

eval({call E1 E2},env1)

= eval(Ef,extend(x,eval(E2,env1),env2))

if eval(E1,env1) = <{fun {x} Ef}, env2>

= error! otherwise -- but this doesn't happen

eval({with {x E1} E2},env) = eval(E2,extend(x,eval(E1,env),env))

eval({if E1 E2 E3},env) = eval(E2,env) if eval(E1,env) is true

= eval(E3,env) otherwise

eval(x,env) = lookup(x,env)

eval({+ E1 E2},env) = eval(E1,env) + eval(E2,env)

...

eval({fun {x} E},env) = <{fun {x} E}, env>

eval({call E1 E2},env1)

= eval(Ef,extend(x,eval(E2,env1),env2))

if eval(E1,env1) = <{fun {x} Ef}, env2>

= error! otherwise -- but this doesn't happen

eval({with {x E1} E2},env) = eval(E2,extend(x,eval(E1,env),env))

eval({if E1 E2 E3},env) = eval(E2,env) if eval(E1,env) is true

= eval(E3,env) otherwise

Do we need to add types to these rules?

(Choose the best answer.)

- Yes
- No
- Yes because the language is lazy
- Yes because if the language is typed then code execution must be typed as well
- No because types only exist in the compiler and the code is executed in an untyped language