2014-04-22 58 views
0

我需要編寫一個方案函數,該函數返回一個函數,然後接受另一個參數,例如一個列表,然後返回所需的結果。在這個例子中(c?r "arg")將返回 - (car(cdr - 這隨後採取list參數返回2返回函數的Scheme函數

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

我的問題是我怎麼能返回接受另一ARG在嬌小的功能?

回答

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

它非常類似於克里斯的版本(多以前fold-right),但我做reverse這樣我就可以在返回的過程中使用fold。我通過查看字符來選擇carcdr中的哪一個。

編輯

這裏是另一種版本更預處理。當運行#\ d's時,它使用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)))))) 
+0

'列表ref'和'LIS T-tail'?不知道如何使用這些來解決這個特定的問題。我想我不明白你的意思是「壓縮」。 :-) –

+0

@ ChrisJester-Young類似這樣的東西..在寫這篇文章之後,我想知道Racket如何實現'compose1' – Sylwester

+0

@Sylwester它大致等於'(define(my-compose1。fs) (foldr(lambda(fg) (lambda(x)(f(gx))))身份fs))' – Wes

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