1

所以这是我的问题(概括为抽象情况)。一般是口译员。

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

)

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

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

还有其他合适的方法吗?

4

2 回答 2

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)))

[我选择将位置定义为不变。]

如果您愿意,您可以选择另一种方法,但从根本上改变了机器人的位置,并且这种改变将在您的代码中以某种方式出现。为什么不使用最简单、最直接的方法?

于 2013-03-10T17:59:43.460 回答
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只是破坏列表的一种简单方法,请参阅它的方案实现)但它似乎是第一个的复杂版本。

于 2013-03-10T18:06:21.127 回答