球拍中的功能,用于在符号列表中交换两个符号

时间:2016-11-05 01:31:57

标签: racket

我试图在球拍中使用高阶函数编写一个函数,它使用两个符号,sym1和sym2以及一个符号列表,并返回列表,每个sym1和sym2实例都被交换。

我想出了如何使用累加器函数执行此操作,但我只是好奇这对于高阶函数是如何工作的,因为它们需要一个参数函数,而不是单个变量。谢谢!

  (define (swapper/ho str1 str2 los)
  (local
    [(define (swapper-acc los acc)
       (cond
         [(empty? los) acc]
         [(symbol=? str1 (first los))
          (swapper-acc (rest los) (append acc (list str2)))]
         [(symbol=? str2 (first los))
          (swapper-acc (rest los) (append acc (list str1)))]
         [else
          (swapper-acc (rest los) (append acc (list (first los))))]))]
    (swapper-acc los empty)))

1 个答案:

答案 0 :(得分:0)

对于具有更高阶函数的解决方案,请不要再看了 - foldr可以解决这个问题:

(define (swapper/ho str1 str2 los)
  (foldr (lambda (e acc)
           (cond ((symbol=? e str1) (cons str2 acc))
                 ((symbol=? e str2) (cons str1 acc))
                 (else (cons e acc))))
         '()
         los))

此外,您的解决方案可以改进 - 在构建输出列表时使用append是一个坏主意(效率非常低),请改用cons。实际上,这正是您使用通常的模板递归遍历列表所解决的问题,您甚至不需要本地帮助器或累加器:

(define (swapper/ho str1 str2 los)
  (cond ((empty? los)
         empty)
        ((symbol=? str1 (first los))
         (cons str2 (swapper/ho str1 str2 (rest los))))
        ((symbol=? str2 (first los))
         (cons str1 (swapper/ho str1 str2 (rest los))))
        (else
         (cons (first los) (swapper/ho str1 str2 (rest los))))))

例如:

(swapper/ho 'x 'y '(a x b c y d x y))
=> '(a y b c x d y x)