[英]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.