返回函数的Scheme函数

时间:2014-04-22 00:00:02

标签: scheme

我需要编写一个scheme函数,该函数作为函数返回,然后接受另一个参数,例如列表,然后返回所需的结果。在此示例中,(c?r "arg")将返回 - (car(cdr - 然后随后将list参数返回2

> ((c?r "ar") '(1 2 3 4))
2
> ((c?r "ara") '((1 2) 3 4))
2

我遇到的问题是如何返回一个接受另一个arg的函数?

3 个答案:

答案 0 :(得分:0)

以下是编写此类函数的方法:

(define (c?r cmds)
  (lambda (lst)
    (let recur ((cmds (string->list cmds)))
      (if (null? cmds)
          lst
          (case (car cmds)
            ((#\a) (car (recur (cdr cmds))))
            ((#\d) (cdr (recur (cdr cmds))))
            (else (recur (cdr cmds))))))))

请注意,我使用d来表示cdr,而不是r(这对我来说毫无意义)。您还可以使用string-fold-right(需要SRFI 13)更简洁地撰写此内容:

(define (c?r cmds)
  (lambda (lst)
    (string-fold-right (lambda (cmd x)
                         (case cmd
                           ((#\a) (car x))
                           ((#\d) (cdr x))
                           (else x)))
                       lst cmds)))

答案 1 :(得分:0)

只想添加我的演奏。使用SRFI-1

(import (rnrs)
        (only (srfi :1) fold)) ;; require fold from SRFI-1

(define (c?r str)
  (define ops (reverse (string->list str)))
  (lambda (lst)
    (fold (lambda (x acc)
            ((if (eq? x #\a) car cdr) ; choose car or cdr for application
             acc))
          lst
          ops)))

它非常类似于Chris'版本(更多以前的fold-right),但我执行了reverse,因此我可以在返回的过程中使用fold。我通过查看字符来选择要调用carcdr中的哪一个。

修改

这是一个具有更多预处理功能的替代版本。当运行#\ d时,它会使用tail-reflist-tail作为快捷方式。

(define (c?r str)
  (let loop ((druns 0) (ops (string->list str)) (funs '()))
    (cond ((null? ops) 
           (let ((funs (reverse 
                        (if (zero? druns)
                            funs 
                            (cons (lambda (x) 
                                    (list-tail x druns)) 
                                  funs)))))
             (lambda (lst)
               (fold (lambda (fun lst)
                       (fun lst))
                     lst
                     funs))))
          ((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
          ((= druns 0)         (loop 0 (cdr ops) (cons car funs)))
          (else (loop 0 (cdr ops) (cons (lambda (x) 
                                          (list-ref x druns)) 
                                        funs))))))

这可以在#!球拍中更简单。我们跳过reverse,只做(apply compose1 funs)

(define (c?r str)
  (let loop ((druns 0) (ops (string->list str)) (funs '()))
    (cond ((null? ops) 
           (let ((funs (if (zero? druns)
                           funs 
                           (cons (lambda (x) 
                                   (list-tail x druns)) 
                                 funs))))
             (apply compose1 funs)))
          ((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
          ((= druns 0)         (loop 0 (cdr ops) (cons car funs)))
          (else (loop 0 (cdr ops) (cons (lambda (x) 
                                          (list-ref x druns)) 
                                        funs))))))

答案 2 :(得分:0)

假设compose程序:

(define (compose funs . args)
  (if (null? funs)
      (apply values args)
      (compose (cdr funs) (apply (car funs) args))))

(compose (list cdr car) '(1 2 3 4))
=> 2

c?r可以用compose来定义,如此:

(define (c?r funs)
  (lambda (e) 
    (compose 
     (map
      (lambda (f) (if (char=? f #\a) car cdr))
      (reverse (string->list funs)))
     e)))

然后

((c?r "ar") '(1 2 3 4))
=> 2
((c?r "ara") '((1 2) 3 4))
=> 2