【问题标题】:shorten the repetitive lines of code缩短重复的代码行
【发布时间】:2016-06-27 05:59:42
【问题描述】:

我使用 temp 将值保留在搜索列表中的临时值,从最大数量的 temp (temp-5) 到最小数量的 temp (temp-1)。我想在搜索列表的撤消功能中添加此功能。如果我使用高达 temp-100 而不是 temp-1 到 temp-5,如何将代码行缩短为循环?如果我使用“for 循环”,我在哪里放置 cond?

#lang racket
(define temp-flag 0)
(define temp-1 '())
(define temp-2 '())
(define temp-3 '())
(define temp-4 '())
(define temp-5 '())
(define search-list '(1 2 3 4 5 6 7 8 9 10))
(define (place-temp tf)
  (cond
    [(equal? tf 1)
     (set! temp-1 search-list)
     (set! temp-flag 5)]
    [(equal? tf 2)
     (set! temp-2 search-list)
     (set! temp-flag 1)]
    [(equal? tf 3)
     (set! temp-3 search-list) (set! temp-flag 2)]
    [(equal? tf 4)
     (set! temp-4 search-list) (set! temp-flag 3)]
    [(set! temp-5 search-list) (set! temp-flag 4)]
    ))  

 (place-temp temp-flag)

【问题讨论】:

  • 只需将临时列表放入向量中,并使用tf 作为索引。
  • place-temp 需要解决的更大目标是什么?

标签: loops for-loop recursion scheme racket


【解决方案1】:

您的问题的基本解决方案是 Michael Vehrs 所建议的。第一次(侵入性最小)尝试可能是这样的:

    (define temp-flag 0)
    (define search-list '(1 2 3 4 5 6 7 8 9 10))

    (define *num-of-temps* 5) ;; you will just have to change it to 100
    (define *temps* (make-vector *num-of-temps* '()))

    (define (next-temp-flag tf)
      (cond ((= tf 1) *num-of-temps*)
        ((and (> tf 1) (< tf *num-of-temps*)) (- tf 1))
        (else (- *num-of-temps* 1))))

    (define (place-temp tf)
      (vector-set! *temps* (- tf 1) search-list)
      (set! temp-flag (next-temp-flag tf)))

从 temp-flag 的角度来看,它的工作原理完全相同。但这不是一个很酷的程序,所以让我们尝试改进它。

首先,这个 next-temp-flag 有点奇怪,但它准确地模仿了你的 cond 语句关于 tf 的行为临时标志。 我假设您使用 temp-flag 仅用于索引 temp-1temp-2 等,并且您不在乎tf 大于 5(或 100,或通常大于 *num-of-temps*)。所以第一件事你可以简化一下:

    (define (next-temp-flag tf)
      (if (= tf 1) *num-of-temps* (- tf 1)))

现在第二件事是向量(cf https://docs.racket-lang.org/reference/vectors.html)中的位置(''indexes'')从 0 开始,而不是 1,例如你的 temp-1 现在是 *(vector-ref temps 0)*。所以你可以像这样使用''减少的tfs'':

    (define (next-temp-flag tf)
      (if (= tf 0) (- *num-of-temps* 1) (- tf 1)))

    (define (place-temp tf)
      (vector-set! *temps* tf search-list)
      (set! temp-flag (next-temp-flag tf)))

显然(或不是;))这个 next-temp-flag 现在可以用模函数表示:

    (define (next-temp-flag tf) (modulo (- tf 1) *num-of-temps*))

...如果您想要更短的代码,您可以同样将其内联到 place-temp

最后一件事是命名约定:也许您刚刚使用这些 define 设置了一个最小示例,但如果您的项目中确实有这些“全局变量”,那么命名约定是使用星号,因此您宁愿使用 *search-list**temp-flag*。 另请注意,place-temp 会导致副作用,因此您可能希望将其称为 place-temp!。如果您打算仅将 place-temp! 应用于 *temp-flag*,则可以完全放弃该参数。并且可能 *temp-position* 听起来比 *temp-flag* 更容易,因为它现在是一个位置。 所以总结一下,你可能会以这样的方式结束:

    (define *num-of-temps* 5) ;; you will just have to change it to 100
    (define *temps* (make-vector *num-of-temps* '()))

    (define *temp-position* (- *num-of-temps* 1)) ;; because (modulo -1 n) is n-1.
    (define *search-list* '(1 2 3 4 5 6 7 8 9 10))

    (define (place-temp!)
      (vector-set! *temps* *temp-position* *search-list*)
      (set! *temp-position* (modulo (- *temp-position* 1) *num-of-temps*)))

    (place-temp!)

抱歉,答案太长了,但正如诗人所说“我没有足够的时间写一个较短的答案”。我还怀疑,如果您想实现撤消,您可能需要其他东西(堆栈而不是循环缓冲区)——但这超出了您的问题。

祝你的项目好运!

PS 我希望当您习惯于方案时,您将减少对全局变量和过程的依赖,而更多地依赖本地绑定和函数(正如另一位诗人所说的“保持功能,我的朋友!”)。但事情需要时间,最重要的是你喜欢你的黑客行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    相关资源
    最近更新 更多