如何以编程方式扩展racket中的let*系列函数

问题描述 投票:0回答:1

背景

这个问题与家庭作业无关,但我不希望有人为我做作业。

我有一项作业,不鼓励过度使用

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
用法,但这感觉像是可以通过编程来完成的事情,所以我将其视为编程练习。

我尝试过的事情

scheme racket let
1个回答
0
投票
在这里。我有一个答案,希望能作为以后更好答案的起点。这是一个简单的函数,它扩展

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
 的实例。

© www.soinside.com 2019 - 2024. All rights reserved.