Skip to content

Instantly share code, notes, and snippets.

@vu3rdd
Created September 4, 2012 10:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vu3rdd/3619542 to your computer and use it in GitHub Desktop.
Save vu3rdd/3619542 to your computer and use it in GitHub Desktop.
let, let* and named-let
#lang racket
(require rackunit)
(define (interpret expr)
(match expr
[`(let ,(? (lambda (b) (or (empty? b) (pair? b))) bindings) ,body ...)
(let->combination expr)]
[`(let* ,bindings ,body ...)
(let*->nested-lets expr)]
[`(let ,(? symbol? name) ,bindings ,body ...)
(named-let->combination expr)]))
(define (let->combination expr)
(let ([bindings (second expr)]
[body (cddr expr)])
(let ([vars (map first bindings)]
[vals (map second bindings)])
`((lambda ,vars ,@body) ,@vals))))
(define (let*->nested-lets lexpr)
(match lexpr
[`(let* (,first-binding ,rest-bindings ...) ,body ...)
`(let (,first-binding) ,(let*->nested-lets `(let* ,rest-bindings ,@body)))]
[`(let* () ,body ...) `(let () ,@body)]))
(define (named-let->combination lexpr)
(match-let* ([`(let ,name ,bindings ,body ...) lexpr]
[`((,var ,val) ...) bindings])
`(begin (define ,name (lambda ,var ,@body))
(,name ,@val))))
;; test code
(define test-ns (make-base-namespace))
;; tests for let
(check-equal? (eval (interpret '(let ([x 42]) x)) test-ns) 42)
(check-equal? (eval (interpret '(let ([x 3]
[y 10])
(+ x y)
(* x y))) test-ns) 30)
(check-equal? (eval (interpret '(let () (+ 20 22))) test-ns) 42)
;; tests for let*
(check-equal? (eval (interpret '(let* ([x 2]
[y (* x 10)])
(+ x y)))
test-ns)
22)
;; test for named-let
(check-equal? (eval (interpret '(let loop ([n 0])
(if (= n 10)
(+ n 32)
(loop (add1 n)))))
test-ns)
42)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment