[英]How would I write a function in Dr. Racket which consumes a list of numbers and produces a new list of numbers which have been mapped?
[英]How would I write a function in Dr. Racket which consumes a list of 2 possible symbols and replaces them with something else?
我如何在 Dr. Racket 中編寫一個 function,它使用 2 個可能的符號列表('c 或 'v)並將它們替換為其他符號? 如果符號是 'c,那么它會被替換為 'c 'v 如果符號是 'v,那么它會被替換為 'v 'c
到目前為止,這是我的代碼:
(define (awesome c)
(cond
[(equal? c 'c) (list 'c 'v)]
[else (list 'v 'c)]))
(define (substitute los)
(map awesome los))
如果我輸入:
(substitute (list 'c 'v 'c 'c))
我想要的 output 是
(list 'c 'v 'v 'c 'c 'v 'c 'v)
相反,我得到:
(list (list 'c 'v) (list 'v 'c) (list 'c 'v) (list 'c 'v))
為什么會這樣? 如何更正我的代碼以獲得正確的 output? 謝謝。
輸入中的每個符號都生成 output 中兩個符號的列表。使用append
組合列表,例如:
scratch.rkt> (append '(c v) '(v c) '(c v) '(c v))
'(c v v c c v c v)
由於map
正在創建一個包含子列表的列表,請使用apply
將append
應用於子列表:
(define (substitute los)
(apply append (map awesome los)))
示例交互:
scratch.rkt> (substitute (list 'c 'v 'c 'c))
'(c v v c c v c v)
您可以通過使用術語重寫規則列表來采取更靈活的方法。 這將允許您在不更改代碼的情況下更改替換規則。 術語重寫規則可以表示為列表的列表,用箭頭將輸入術語與重寫分開:
(define cv-rules '((c -> c v)
(v -> v c)))
定義幾個函數來獲取術語的規則和規則的重寫列表很有用。 將這些操作抽象為函數使得以后更改規則的表示更容易,並有助於保持代碼清晰:
(define (get-rule term rules)
(assoc term rules))
(define (get-rewrites rule)
(cddr rule))
這個get-rewrites
rewrites function 可以用在另一個 function 中,它根據規則重寫一個術語。 在這里,任何沒有特定規則的符號僅在列表中單獨返回:
(define (rewrite-term x rules)
(let ((rule (get-rule x rules)))
(if rule
(get-rewrites rule)
(list x))))
現在可以將rewrite-term
function 與重寫規則一起映射到輸入上。 和以前一樣,映射結果是一個子列表列表,因此在返回之前將append
應用於結果:
(define (rewrite terms rules)
(apply append (map (lambda (x) (rewrite-term x rules)) terms)))
現在,您可以通過定義一組新的重寫規則輕松更改替換的方式。
示例交互:
scratch.rkt> (rewrite '(c v c c) cv-rules)
'(c v v c c v c v)
scratch.rkt> (rewrite '(c v c x c) cv-rules)
'(c v v c c v x c v)
通過對rewrite-term
function 的小改動,您可以將重寫規則遞歸地應用於嵌套的術語列表。 當要重寫的術語本身是一個沒有重寫規則的非空列表時,將對該術語調用rewrite
。 請注意,所有重寫在返回之前都包含在列表中。 這個新的 function 對於原始規則的行為與以前一樣,但也允許更復雜的規則:
(define (rewrite-term x rules)
(let ((rule (get-rule x rules)))
(cond (rule (get-rewrites rule))
((pair? x) (list (rewrite x rules)))
(else
(list x)))))
示例交互:
scratch.rkt> (define cv2-rules '((c -> v)
(v -> (c v))))
scratch.rkt> (rewrite '(c v c c) cv2-rules)
'(v (c v) v v)
scratch.rkt> (rewrite '(v (c v) v v) cv2-rules)
'((c v) (v (c v)) (c v) (c v))
scratch.rkt> (rewrite '((c v) (v (c v)) (c v) (c v)) cv2-rules)
'((v (c v)) ((c v) (v (c v))) (v (c v)) (v (c v)))
你的方法很好。 您所要做的就是將map
替換為append-map
。
(define (awesome c)
(cond ((equal? c 'c) (list 'c 'v))
((equal? c 'v) (list 'v 'c))))
(define (substitute los)
(append-map awesome los))
(substitute (list 'c 'v 'c 'c))
;; '(c v v c c v c v)
;; desired: (list 'c 'v 'v 'c 'c' 'v 'c 'v)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.