所以这是我的问题(概括为抽象情况)。它通常是一名翻译。
我有一个需要解析输入列表的程序,并根据其元素顺序调用一些需要修改变量的函数。函数是单独定义的,并由选择(cond 。我需要更新的3个变量包含有关当前情况的信息(确切地说 - 机器人位置,迷宫和机器人方向)。之前函数的结果用于下一个函数(即使用更新的变量)。
(define func-a ... )
(define func-b ... )
(define (main-func <maze> <orientation> <coordinates> <list with commands>)
;; here I parse the list and choose which function to call
;; output must contain (list <new-maze> <new-orientation> <new-coordinates>))
)
我可以使用哪些方案工具来更新这些变量?我考虑了几个选择:
还有其他正确的方法吗?
答案 0 :(得分:1)
仅仅因为Scheme被认为是'功能语言'并不禁止你使用'set!' - 毕竟它存在于要使用的语言中。因此没有错:
(define-record-type position (fields x y z))
(define robot-position (make-position 0.0 0.0 0.0))
(define update-robot-position (new-x new-y new-z)
(set! robot-position (make-position new-x new-y new-x)))
[我选择将职位定义为不变量。]
如果你愿意,你可以选择另一种方法,但从根本上说,机器人的位置发生了变化,并且代码中的变化是某种方式。为什么不使用最简单,最直接的方法?
答案 1 :(得分:1)
你必须保留一些状态(以及读取文件),因此不会有纯函数编程,你必须接受一些偏差。
一般方法是将共享对象保留为某个元函数中的本地对象,比如parse
,并通过调用您的函数来更新它,比如parse-one
,parse-two
,等等。
现在你需要一种方法来更新它们。
您可以通过在范围内定义parse-one
和parse-two
,使其可见:
(let ((state (make-state)))
(let ((parse-one (lambda () ...))
(parse-two (lambda () ...)))
....))
或者您使用返回值:
(let ((state (make-state)))
...
(set! state (parse-one state))
...)
还有第三种方法,叫做OOP。在一个闭包中定义所有这些,因此他们可以共享一些数据:
(define (make-parser)
(let ((state (make-state))
(let (((parse-one (lambda () ...))
((parse-two (lambda () ...))
((get-state (lambda () state)))
(list parse-one parse-two get-state))))
(destructuring-bind (parse-one parse-two get-state) (make-parser)
...
(parse-one)
...
(get-state))
(destructuring-bind只是破坏列表的一种简单方法,看它是scheme implementation)但它似乎是第一个的复杂版本。