我最近开始使用 PLT-Redex,我想知道是否有人可以给我一些关于如何在 Racket 中实现 let* 表达式的指示。
现在我可以像这样写简单的 let 表达式
(let (x (+ 2 4)) in (* x 2))
(let (x (+ 2 4)) in (let (y (* x 2)) in y))
但是,如果我尝试如下复杂的 let 表达式(请参阅我的代码中的测试 4 和 5),我会得到多个输出值:
(let (x (+ 2 4)) in (let (y (* x 2)) in (* y y)))
(let (x (+ 2 4)) in (let (y (* x 2)) in (let (y (* x 2)) in (let (z (+ y 5)) in (+ (+ x y) z)))))
我想像这样重写上面的表达式
(let* ([x (+ 2 4)]
[y (* x 2)]
[z (+ y 5)]
(+ (+ x y) z))
以下是我当前的 Redex 实施,以防有人想提供帮助。
在此先感谢温贝托
#lang racket
(require redex)
(define-language L
(e ::=
v
x
(let (x e) in e)
(e ...)
(aop e e))
(v ::= number integer string boolean)
(x ::= variable-not-otherwise-mentioned)
(aop ::= + - / *)
(p (e ...))
(P (e ... E e ...))
(E ::=
hole
(let (x E) in e)
(aop E e))
);;
(define-metafunction L
[(subst (x_1 any_1 x_1)) any_1]
[(subst (x_1 any_1 x_a)) x_a]
[(subst (x any (let (x e_x) in e_body)))
(let (x (subst (x any e_x))) in e_body)]
[(subst (x any (let (x_a e_xa) in e_body)))
(let (x_a (subst (x any e_xa))) in (subst (x any e_body)))]
[(subst (x any (aop e_1 e_2)))
(aop (subst (x any e_1)) (subst (x any e_2)))]
[(subst (x any v_2)) v_2]
);;
(define L-R
(reduction-relation
L
#:domain p
(-->
(in-hole P (/ number_1 0))
,(error 'DivisionByZeroError)
"error")
(-->
(in-hole P (+ number_1 number_2))
(in-hole P ,(+ (term number_1) (term number_2)))
"add")
(-->
(in-hole P (* number_1 number_2))
(in-hole P ,(* (term number_1) (term number_2)))
"multiply")
(-->
(in-hole P (/ number_1 number_2))
(in-hole P ,(/ (term number_1) (term number_2)))
"divide")
(-->
(in-hole P (- number_1 number_2))
(in-hole P ,(- (term number_1) (term number_2)))
"subtract")
(-->
(in-hole P (let (x_1 e_1) in e_2))
(in-hole P (subst (x_1 e_1 e_2)))
"let")
));;;
(define (test-syntax)
;; Test 1
(test-->> L-R
(term ((+ 2 3)))
(term (5)))
;; Test 2
(test-->> L-R
(term ((let (x (+ 2 4)) in (* x 2))))
(term (12)))
;; Test 3
(test-->> L-R
(term ((let (x (+ 2 4)) in (let (y (* x 2)) in y))))
(term (12)))
;; Test 4 ERROR
; (test-->> L-R
; (term ((let (x (+ 2 4)) in (let (y (* x 2)) in (* y y)))))
; (term (144)))
;; Test 5 ERROR
; (test-->> L-R
; (term ((let (x (+ 2 4)) in (let (y (* x 2)) in (let (y (* x 2)) in (let (z (+ y 5)) in (+ (+ x y) z)))))))
; (term (35)))
);;
(test-syntax)
(module+ test
(test-results))