Question 1 @ 2024-04-09 19:13
What is the biggest problem of using just syntax-rules
as your macro
tool of choice?
- Hygiene is not always desirable
- It is a complicated system compared to just plain symbols and Sexprs
- It is limited in its “computational power” (= not Turing-equivalent)
- Lack of using the full language at the syntax (= compiler) level
- It is effectively a lazy (meta) language
Question 2 @ 2024-04-09 19:16
Considering how adding an excess of macros can make code harder to read, debug, and possibly use — 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 forms with a different binding structure
Question 3 @ 2024-04-09 19:18
Of the following, which are valid reasons for using a type checker?
- Reduce debugging time
- Help with code refactoring
- Lead to better code organization
- Help the compiler generate code that runs more efficiently
- Avoid infinite loops
- Improve IDE features (eg, auto-completions)
Question 4 @ 2024-04-09 19:20
Recall the PICKY language we went over in class last week. Which one of these descriptions of the type judgements/rules of our PICKY language is not true?
-
{+ A B}
: to prove this is aNumber
, we need to prove bothA
andB
areNumber
-
{call F V}
: to prove that this is aτ₂
, we need to proveF
is a(τ₁ -> τ₂)
andV
is aτ₁
-
{fun {x : τ₁} : τ₂ E}
: to prove that this is a(τ₁ -> τ₂)
, we need to prove thatx
is aτ₁
andE
is aτ₂
-
{if C T E}
: to prove that this is aτ
, we need to prove thatC
is aBoolean
, and bothT
andE
are aτ
Question 5 @ 2024-04-09 19:23
Consider the evaluation rules for our new PICKY language, which started as a simple extension of the old FLANG language:
eval(x,env) = lookup(x,env)
eval({+ E1 E2},env) = eval(E1,env) + eval(E2,env)
eval({- E1 E2},env) = eval(E1,env) - eval(E2,env)
eval({= E1 E2},env) = eval(E1,env) = eval(E2,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(B,extend(x,eval(E2,env1),env2))
if eval(E1,env1) = <{fun {x} B}, env2>
= error! otherwise <-- never happens
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
How should these evaluation rules be revised to fit the Picky statically-typed context?
-
We need to add type information for all primite values
-
We need to add type checks for evaluation rules to verify their type according to the type rules (eg, in
+
expressions, check that both sides are numbers) -
Need to add types to places that create a new binding (
fun
andwith
), and maintain them in a new kind of a type environment -
No need to add anything, because the Picky language is lazy
-
There is no need to add anything, since types do not exist at runtime