【问题标题】:Scheme task decomposition - global variable issues方案任务分解——全局变量问题
【发布时间】:2013-03-10 17:46:15
【问题描述】:

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

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

)

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

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

还有其他合适的方法吗?

【问题讨论】:

  • 我认为,您需要更具体一些。方法总是取决于问题,而你提供的信息量是不够的。
  • 我会选择你的第三个选项,将三个变量(代表状态)从函数传递到另一个函数(最好在尾部调用中)。您还可以在更新它们时将这些三元组收集到一个列表中,从而创建一个明确的评估历史(如果您的机器人试图解决迷宫可能会很有用) - 增加列表,例如like here.
  • 如果你在处理状态的过程中坚持这条黑暗而曲折的道路,试图保持纯粹的功能,你最终会进入单子王国。 cs.indiana.edu/cgi-pub/c311/lib/exe/….

标签: list variables scheme


【解决方案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)但它似乎是第一个的复杂版本。

【讨论】:

    【解决方案2】:

    仅仅因为 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)))
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      • 2019-03-15
      • 1970-01-01
      相关资源
      最近更新 更多