Question 1 @ 2025-01-28 18:29
Recall the following bit of code (discussed in HW#2):
What is the purpose of inst
there?
-
It does a type casting for whatever the argument is, so, for example, we could also use
'("1" "2" "3")
or even"123"
as an input. -
Higher-order polymorphic functions in Typed Racket are similar to classes, which need to be instantiated for each call.
-
Polymorphic functions are lazy, so we need to specify when we want to call them inst-antly.
-
It’s an inference hint for Typed Racket, which can be clueless sometimes.
Question 2 @ 2025-01-28 18:31
How many identifiers do we have in this Racket expression:
(let ([x y] [y x])
(list 'x= x 'y= y)))
(Reminder: each identifier comes from one binding instance, and is associated with a scope.)
0..8
Question 3 @ 2025-01-28 18:33
Reminder: this is part of the WAE evaluator code that we saw in class, similar to the AE one:
(cases expr
...
[(Add l r) (+ (eval l) (eval r))]
[(Sub l r) (- (eval l) (eval r))]
...))
Last week, we saw that this doesn’t implement an eager language in itself, it just “inherits” Racket’s behavior (eagerness). There were several similar inherited (“embedded”) features, like having unlimited integers, or exact rationals.
How about the arity of the addition operator in this language, what is its arity?
-
Unary, because
eval
takes in one argument -
Binary, because Racket’s
+
is binary - Binary, because of the WAE BNF, AST, and parser
-
Variable-arity, because Racket’s
+
can take any number of inputs - Whatever Racket does
Question 4 @ 2025-01-28 18:35
Reminder: this is part of the WAE evaluator code that we saw in class, similar to the AE one:
(cases expr
...
[(Add l r) (+ (eval l) (eval r))]
[(Sub l r) (- (eval l) (eval r))]
...))
Last week, we saw that this doesn’t implement an eager language in itself, it just “inherits” Racket’s behavior (eagerness). There were several similar inherited (“embedded”) features, like having unlimited integers, or exact rationals.
How about the direction of evaluating arguments of an operator: do we implement this, or inherit it from Racket?
- Non-sensical question, because it’s a fully-parenthesized language
-
We implement it, since we evaluate
l
before evaluatingr
- It depends on the BNF, AST, and parser
- It depends on the particular operator
- Whatever Racket does
Question 5 @ 2025-01-28 18:37
Which of the following WAE evaluations would lead to an unbound identifier error? (In other words: which of these have free identifiers?)
-
{with {x x} 1}
-
{with {x x} x}
-
{with {x 1} {with {x x} x}}
-
{with {x {with {x 1} x}} x}
Question 6 @ 2025-01-28 18:39
These were the options in the previous question:
- (A)
{with {x x} 1}
- (B)
{with {x x} x}
- (C)
{with {x 1} {with {x x} x}}
- (D)
{with {x {with {x 1} x}} x}
What would change if we did the cheap laziness trick, where we implement lazy evaluation via
(cases expr
...
[(With bound-id named-expr bound-body)
(eval (subst bound-body
bound-id
named-expr))])) ; <-- no eval!
- The first one would not throw an error
- The second one would not throw an error
- The answers would be the same
-
The last two would error, since nested
with
s are impossible when we’re lazy