Scheme任务分解 - 全局变量问题

时间:2013-03-10 17:46:15

标签: list variables scheme

所以这是我的问题(概括为抽象情况)。它通常是一名翻译。

我有一个需要解析输入列表的程序,并根据其元素顺序调用一些需要修改变量的函数。函数是单独定义的,并由选择(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>))

)

我可以使用哪些方案工具来更新这些变量?我考虑了几个选择:

  • 使用(定义然后调用set!(这是不好的样式,因为它不是纯函数式编程);
  • 从后到开调用函数(这不起作用:我还必须检查移动是否有效);
  • 根本不要使这些变量保持不变,尝试将它们作为参数传递给每个函数;

还有其他正确的方法吗?

2 个答案:

答案 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-oneparse-two,等等。

现在你需要一种方法来更新它们。

您可以通过在范围内定义parse-oneparse-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)但它似乎是第一个的复杂版本。