Closed LuKuangChen closed 2 years ago
BTW, I spent 2h trying to implement this with (current-namespace)
and eval
. Eventually, I realized
(current-namespace)
has nothing to do with the current namespace. Rather, it points to the empty namespace unless you parameterize it to something else.In Emacs Lisp:
(let ((x 1))
(+ (let ((f (lambda () x)))
(let ((x 2) (y 3))
(funcall f)))))
evals to 2
. #lang
's equivalent program:
(let ((x 1))
(+ (let ((f (lambda () x)))
(let ((x 2) (y 3))
(f)))))
also evaluates to 2
.
However, in Emacs Lisp:
(let ((x 1))
(+ (let ((f (lambda () x)))
(let ((x 2) (y 3))
(funcall f)))
y))
fails with the error unbound id y
.
With this branch, I think the following program will return 5?
(let ((x 1))
(+ (let ((f (lambda () x)))
(let ((x 2) (y 3))
(f)))
y))
You are right! Thanks for catching that. The new commit re-implements let
with left-left-lambda and should fix the problem.
If I understand correctly, the problem is not even about the error type, but about when the error occurs: a syntax error occurs at compile-time, but test/exn
is meant to catch run-time error.
If that is truly the case, you could use convert-compile-time-error
or convert-syntax-error
to turn a compile-time error into a run-time error.
Although the error being raised is a syntax error, I think the error is raised at runtime:
#lang racket
(require "semantics.rkt")
(deffun (f)
an-unbound-id)
;; You don't see an error unless you uncomment the application.
;(f)
Besides, the documentation of test/exn
says that it only catches errors raised by PLAI's error
function.
Ah, right!
Thanks for asking!
This PR is now ready to merge. It makes the following changes in addition to what #12 requires:
let
with #%app
rather than doing it directlydeffun
with defvar
rather than doing it directly
Fix #12