这个问题与家庭作业无关,但我不希望有人为我做作业。
let
、let*
以及与“功能性思考”类似的功能。但是,我仍然很少使用它们,因为它们帮助我减少函数中代码的重用并使代码更具可读性/可写性。
我也理解使用
let
的表达式可以扩展为仅使用 lambda
,如下所示。
#lang racket
; using let
(let ([x 1] [y 2]) (+ x y))
; with lambda
((lambda (x y) (+ x y)) 1 2)
有没有办法以编程方式完成这种扩展?理想情况下,我能够读取整个文件并对其进行转换,但是可以将代码作为参数传递给函数的解决方案也可以工作。
> (expand-let '(let ([x 1] [y 2]) (+ x y)))
'((lambda (x y) (+ x y)) 1 2)
我只需要能够扩展
let
和 let*
来实现我的目的,但如果这可以应用于所有 “本地绑定”球拍功能,那就太酷了:let
,let*
,letrec
、let-values
、let*-values
、letrec-values
等等。老实说,我可以手动扩展作业中的 let
用法,但这感觉像是可以通过编程来完成的事情,所以我将其视为编程练习。
let
和 letrec
的扩展,但是是手动实现的。let
、let*
和letrec
范围的有益讨论。
#lang scheme
,但这题使用了
#lang racket
Racket的沙盒评估,但我不确定这就是我正在寻找的(建议值得赞赏)。看起来这用于提供对代码评估方式的一些控制,但我正在寻找的不是对评估的控制。这是关于扩展用于本地绑定的函数,当它们可以使用 lambda
重写时。
> (syntax-e (expand '(let ([x 1] [y 2]) (+ x y))))
'(#<syntax:/Applications/Racket v8.11.1/collects/racket/private/qq-and-or.rkt:193:51 let-values>
#<syntax (((x) (quote 1)) ((y) (quote 2)))>
#<syntax:/Applications/Racket v8.11.1/collects/racket/private/kw.rkt:1263:25 (#%app + x y)>)
only let
。解决方案
(define (expand-let atomized-expr)
(expand-let-helper (syntax->datum (expand atomized-expr)) (lambda (result) result)))
(define (expand-let-helper parse-tree return)
(define (expand-let-bindings bindings)
(map (lambda (binding) (list (caar binding) (expand-let (cadr binding)))) bindings))
(cond
[(null? parse-tree) (return '())]
[(not (pair? parse-tree)) (return parse-tree)]
[(eq? (car parse-tree) '#%app)
(expand-let-helper (cdr parse-tree) (lambda (result) (return result)))]
[(eq? (car parse-tree) '#%top) (return (cdr parse-tree))]
[(eq? (car parse-tree) 'let-values)
(let* ([bindings (cadr parse-tree)]
[body (cddr parse-tree)]
[expanded-bindings (expand-let-bindings bindings)]
[vars (map car expanded-bindings)]
[vals (map cadr expanded-bindings)])
(expand-let-helper body
(lambda (result)
(return `((lambda (,@vars) ,@result) ,@vals)))))]
[else
(expand-let-helper (cdr parse-tree)
(lambda (cdr-result)
(expand-let-helper (car parse-tree)
(lambda (car-result)
(return (cons car-result cdr-result))))))]))
在此处查看结果:
Welcome to Racket v8.11.1 [cs].
> (require "main.rkt")
> ((lambda (x y) (let ((a (+ x y)) (b (- x y))) (* a b))) 1 2)
-3
> (expand-let '((lambda (x y) (let ((a (+ x y)) (b (- x y))) (* a b))) 1 2))
'((lambda (x y) ((lambda (a b) (* a b)) (+ x y) (- x y))) '1 '2)
> (eval (expand-let '((lambda (x y) (let ((a (+ x y)) (b (- x y))) (* a b))) 1 2)))
-3
说明(syntax->datum (expand <quoted expression>))
用于获取仅包含符号的语法树
> (syntax->datum (expand '(let ((x 1)) (+ x 1))))
'(let-values (((x) '1)) (#%app + x '1))
辅助函数递归地分析解析树,并用适当的 let-values
替换来替换
lambda
的实例。