讓我專注於單一功能show-deck
。我看到它在做什麼,但遞歸可以簡化一點。使它更容易閱讀可能會稍微低效,但我們在這裏談論52個卡... :)
內部和外部循環糾纏在原始代碼中。這裏有一個版本,理順了那些紛繁他們:
(define (show-deck1 first-list second-list)
(define (outer-loop first-list second-list)
(cond
((null? first-list)
'())
(else
(append (inner-loop (car first-list) second-list)
(outer-loop (cdr first-list) second-list)))))
(define (inner-loop x second-list)
(cond
((null? second-list)
'())
(else
(cons (cons x (car second-list))
(inner-loop x (cdr second-list))))))
(outer-loop first-list second-list))
我們可以應用的簡化:與定義這種方式表達,它更容易看到map
可以用來做inner-loop
。
(define (show-deck2 first-list second-list)
(cond
((null? first-list)
'())
(else
(define x (car first-list))
(append (map (lambda (y) (cons x y)) second-list)
(show-deck2 (cdr first-list) second-list)))))
這使得更容易看到外迭代的結構。我們可以採取map
一步,並用其來進行內部和外部環圈,並用(apply append ...)
到平由嵌套使用map
推出了子:
(define (show-deck3 first-list second-list)
(apply append
(map (lambda (x)
(map (lambda (y) (cons x y)) second-list))
first-list)))
你的版本通過巧妙地完全避免了從(apply append ...)
東西線程計算,但這是以犧牲一些可讀性爲代價的。避免(apply append ...)
,仍然可以得到容易看到的嵌套循環結構的好處的一種方法是使用foldr
方法,而不是一個map
方法:
(define (foldr f acc l)
(cond
((null? l) acc)
(else
(f (car l)
(foldr f acc (cdr l))))))
(define (show-deck first-list second-list)
(foldr (lambda (x acc)
(foldr (lambda (y acc)
(cons (cons x y) acc))
acc
second-list))
'()
first-list))
這應該與你的原代碼前一樣。儘管如此,它將循環降級到foldr
,以便所有那些iter
函數都消失爲foldr
的用法。個人而言,如果我正在使用完整球拍寫作,我只需使用for
循環進行編碼即可。 :)它看起來像這樣:
;; If we're allowed to use full Racket:
(define (show-deck first-list second-list)
(for*/list ([x first-list]
[y second-list])
(cons x y)))
也許你應該嘗試寫一個更難的方案變種。球拍相當不同,更容易。我個人不喜歡'如果'。我可以閱讀和理解整個計劃。 – 2012-02-24 18:14:52