简体   繁体   English

我将如何在 Dr. Racket 中编写一个 function,它使用 2 个可能的符号列表并将它们替换为其他符号?

[英]How would I write a function in Dr. Racket which consumes a list of 2 possible symbols and replaces them with something else?

How would I write a function in Dr. Racket which consumes a list of 2 possible symbols ('c or 'v) and replaces them with something else?我如何在 Dr. Racket 中编写一个 function,它使用 2 个可能的符号列表('c 或 'v)并将它们替换为其他符号? If the symbol is 'c, then it gets replaced with 'c 'v If the symbol is 'v, then it gets replaced with 'v 'c如果符号是 'c,那么它会被替换为 'c 'v 如果符号是 'v,那么它会被替换为 'v 'c

Here is my code so far:到目前为止,这是我的代码:

(define (awesome c)
  (cond
    [(equal? c 'c) (list 'c 'v)]  
    [else (list 'v 'c)]))

(define (substitute los)
  (map awesome los))

If I type in:如果我输入:

(substitute (list 'c 'v 'c 'c))

My desired output is我想要的 output 是

(list 'c 'v 'v 'c 'c 'v 'c 'v)

Instead, I get:相反,我得到:

(list (list 'c 'v) (list 'v 'c) (list 'c 'v) (list 'c 'v))

Why is this happening?为什么会这样? How can I correct my code to achieve the correct output?如何更正我的代码以获得正确的 output? Thanks.谢谢。

A Simple Solution一个简单的解决方案

Each symbol in the input is generating a list of two symbols in the output. Use append to combine the lists, eg:输入中的每个符号都生成 output 中两个符号的列表。使用append组合列表,例如:

scratch.rkt> (append '(c v) '(v c) '(c v) '(c v))
'(c v v c c v c v)

Since map is creating a list that contains sublists, use apply to apply append to the sublists:由于map正在创建一个包含子列表的列表,请使用applyappend应用于子列表:

(define (substitute los)
  (apply append (map awesome los)))

Sample interaction:示例交互:

scratch.rkt> (substitute (list 'c 'v 'c 'c))
'(c v v c c v c v)

Adding Some Flexibility增加一些灵活性

You could take a more flexible approach by using a list of term rewriting rules.您可以通过使用术语重写规则列表来采取更灵活的方法。 This would allow you to change the substitution rules without changing your code.这将允许您在不更改代码的情况下更改替换规则。 The term rewriting rules could be represented as a list of lists, with an arrow separating the input term from the rewrites:术语重写规则可以表示为列表的列表,用箭头将输入术语与重写分开:

(define cv-rules '((c -> c v)
                   (v -> v c)))

It is useful to define a couple of functions that get the rule for a term and a list of rewrites from a rule.定义几个函数来获取术语的规则和规则的重写列表很有用。 Abstracting these operations to functions makes it easier to change the representation of a rule later, and helps keep the code clear:将这些操作抽象为函数使得以后更改规则的表示更容易,并有助于保持代码清晰:

(define (get-rule term rules)
  (assoc term rules))

(define (get-rewrites rule)
  (cddr rule))

This get-rewrites function can be used in another function that rewrites a term based on the rules.这个get-rewrites rewrites function 可以用在另一个 function 中,它根据规则重写一个术语。 Here, any symbol which does not have a specific rule is just returned in a list by itself:在这里,任何没有特定规则的符号仅在列表中单独返回:

(define (rewrite-term x rules)
  (let ((rule (get-rule x rules)))
    (if rule
        (get-rewrites rule)
        (list x))))

Now the rewrite-term function can be mapped over the input, together with rewrite rules.现在可以将rewrite-term function 与重写规则一起映射到输入上。 As before, the mapping results in a list of sublists, so append is applied to the result before returning:和以前一样,映射结果是一个子列表列表,因此在返回之前将append应用于结果:

(define (rewrite terms rules)
  (apply append (map (lambda (x) (rewrite-term x rules)) terms)))

Now you can easily change the way that substitutions are made by defining a new set of rewrite rules.现在,您可以通过定义一组新的重写规则轻松更改替换的方式。

Sample interactions:示例交互:

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)

Recursively Rewriting递归重写

With a small change to the rewrite-term function, you can apply the rewrite rules recursively to nested lists of terms.通过对rewrite-term function 的小改动,您可以将重写规则递归地应用于嵌套的术语列表。 When the term to rewrite is itself a nonempty list with no rewrite rule, rewrite is called on that term.当要重写的术语本身是一个没有重写规则的非空列表时,将对该术语调用rewrite Note that all rewrites are wrapped in lists before being returned.请注意,所有重写在返回之前都包含在列表中。 This new function behaves as before for the original rules, but allows more complex rules, too:这个新的 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)))))

Sample interactions:示例交互:

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)))

You approach was quite good.你的方法很好。 All you have to do is to replace map by append-map .您所要做的就是将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.

相关问题 我将如何在 Racket 博士中编写一个 function 消耗一个数字列表并生成一个已映射的新数字列表? - 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? 在 Dr. Racket 中,如何以相反的顺序显示列表中的 2 个元素? - In Dr. Racket, how would I display the 2 elements in a list in the opposite order? 如何从列表转换为矢量此功能? (方案-DR球拍) - How do I convert from list to vector this function? (scheme-dr racket) Racket博士:使用抽象列表功能从列表中删除元素 - Dr. Racket: Removing elements from a list using abstract list functions 我正在尝试在球拍(删除所有 xx elt)中编写一个函数,它返回一个新列表,其中删除了所有出现的 elt - I'm trying to write a function in racket (delete-all xx elt) which returns a new list with all occurrences of elt removed 我想编写一个函数,用列表中的其他值替换字符串的某些部分 - I want to write a function that replaces certain parts of a string with other values from a list 计算平均值或Scheme中带字母的列表 - Dr.Racket - computing average or a list with letters in Scheme - Dr.Racket 我应该使用 HashMap、List 还是其他东西? - Should I use a HashMap, List, or something else? 在Racket中,如何返回包含两个不同字典中出现的所有键的列表 - In Racket how do I return a list that contains all the keys which occur in two different dictionaries Racket - 将引用列表中的符号自动转换为小写 - Racket - turns symbols in quoted list to lowercase automatically
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM