lambda# could be improved by doing alpha canonicalization on the formals and body. This would make identical procedures have the same hash even if their formals have different names.
Here is a minimal implementation (not supporting lambda*, let* and letrec):
(define-syntax alpha-canonicalization
(lambda (stx)
(define (make-environment bindings parent)
(append bindings parent))
(define (lookup-environment name environment)
(assq-ref environment name))
(define (make-identifier-counter)
(let ((counter 0))
(lambda _
(let ((value counter))
(set! counter (1+ value))
(datum->syntax #f (string->symbol (format #f "blue-~a" value)))))))
(syntax-case stx ()
((_ form)
(let ((formal-generator (make-identifier-counter)))
(let loop ((expression #'form)
(environment '()))
(syntax-case expression (lambda lambda* let let*)
((lambda (formals ...) body body* ...)
(with-syntax (((new-formals ...) (map formal-generator #'(formals ...))))
(let ((new-environment
(make-environment (map (lambda (old-formal new-formal)
(cons (syntax->datum old-formal)
new-formal))
#'(formals ...)
#'(new-formals ...))
environment)))
#`(lambda (new-formals ...)
#,@(map (lambda (expr)
(loop expr new-environment))
#'(body body* ...))))))
((let ((bindings values) ...) body body* ...)
(with-syntax (((new-bindings ...) (map (lambda (bindin value)
(list (formal-generator) value))
#'(bindings ...)
#'(values ...))))
(let ((new-environment
(make-environment (map (lambda (old-binding new-binding)
(cons (syntax->datum old-binding)
new-binding))
#'(bindings ...)
#'(new-bindings ...))
environment)))
#`(let (new-bindings ...)
#,@(map (lambda (expr)
(loop expr new-environment))
#'(body body* ...))))))
((head rest ...)
(map (lambda (expr)
(loop expr environment))
(cons #'head #'(rest ...))))
(identifier
(or (lookup-environment (syntax->datum #'identifier) environment)
#'identifier)))))))))
`lambda#` could be improved by doing alpha canonicalization on the formals and body. This would make identical procedures have the same hash even if their formals have different names.
Here is a minimal implementation (not supporting `lambda*`, `let*` and `letrec`):
```scheme
(define-syntax alpha-canonicalization
(lambda (stx)
(define (make-environment bindings parent)
(append bindings parent))
(define (lookup-environment name environment)
(assq-ref environment name))
(define (make-identifier-counter)
(let ((counter 0))
(lambda _
(let ((value counter))
(set! counter (1+ value))
(datum->syntax #f (string->symbol (format #f "blue-~a" value)))))))
(syntax-case stx ()
((_ form)
(let ((formal-generator (make-identifier-counter)))
(let loop ((expression #'form)
(environment '()))
(syntax-case expression (lambda lambda* let let*)
((lambda (formals ...) body body* ...)
(with-syntax (((new-formals ...) (map formal-generator #'(formals ...))))
(let ((new-environment
(make-environment (map (lambda (old-formal new-formal)
(cons (syntax->datum old-formal)
new-formal))
#'(formals ...)
#'(new-formals ...))
environment)))
#`(lambda (new-formals ...)
#,@(map (lambda (expr)
(loop expr new-environment))
#'(body body* ...))))))
((let ((bindings values) ...) body body* ...)
(with-syntax (((new-bindings ...) (map (lambda (bindin value)
(list (formal-generator) value))
#'(bindings ...)
#'(values ...))))
(let ((new-environment
(make-environment (map (lambda (old-binding new-binding)
(cons (syntax->datum old-binding)
new-binding))
#'(bindings ...)
#'(new-bindings ...))
environment)))
#`(let (new-bindings ...)
#,@(map (lambda (expr)
(loop expr new-environment))
#'(body body* ...))))))
((head rest ...)
(map (lambda (expr)
(loop expr environment))
(cons #'head #'(rest ...))))
(identifier
(or (lookup-environment (syntax->datum #'identifier) environment)
#'identifier)))))))))
```