我正在使用temp将搜索列表中的值保留为临时值,从最大数量的temp(temp-5)开始到最小数量的temp(temp-1)。我想在search-list的undo功能中添加这个功能。如果我使用temp-100而不是temp-1到temp-5,如何将代码行缩短为循环?如果我使用“for loop”,我在哪里放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)
答案 0 :(得分: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-标志。 我假设您仅使用 temp-flag 来索引 temp-1 , temp-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)中的位置(''index'')从0开始,而不是1,所以例如你的 temp-1 现在是*(vector-ref temps 0)*。所以你可以像这样使用''减去 tf s':
(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我希望当你习惯了方案时,你将更少依赖全局变量和程序,更多地依赖于本地绑定和函数(正如另一位诗人所说''保持功能我的朋友!'')。但事情需要时间,最重要的是你喜欢你的黑客行为。