2012-03-29 94 views
1

我應該構建的函數應該將數字列表作爲參數,並將單個函數作爲輸出執行如下操作:如果列表中的數字是正數,加上它,如果它乘以負數,如果它是0,則平方數。例如,如果我傳遞(4 -1 0),它應該返回一個函數,它接受一個參數,將其加上4,乘以-1,將其平方並返回。計劃中的函數生成器

我認爲我走在正確的軌道上,但在這一點上我感到非常困惑。我不一定在尋找解決方案,但是到達目的地的任何幫助都會很棒。這是我到目前爲止有:

(define (buildseries L) 
    (define (a x) 
    (lambda (y) (+ x y))) 
    (define (m x) 
    (lambda (y) (* x y))) 
    (define (s x) 
    (lambda (x) (* x x))) 
    (define (funcfind d) 
    (cond 
    [(null? d) (a 0)] 
    [(> d 0) (a d)] 
    [(= d 0) (s d)] 
    [(< d 0) (m d)])) 
    (funcfind (first L))) 

((buildseries '(2)) 2) 

我不知道如何建立一個功能是其他功能的複合......只是感覺丟在這裏。

+0

回到基礎。你的輸入是一個列表,一個遞歸數據類型。寫一個遞歸函數。列表的兩種變體是什麼? .... – 2012-03-29 10:59:21

回答

1

Jon的回答非常好。你應該儘可能地實現它。如果你需要,你也可以參照這裏我的答案(不遵循喬恩的方法,因爲我寫了我大部分的回答,他發佈之前,他的):

(define (fun nums) 
    (lambda (x) 
    (let loop ((nums nums) 
       (value x)) 
     (if (null? nums) value 
      (let ((num (car nums)) 
       (rest (cdr nums))) 
      (cond ((positive? num) 
        (loop rest (+ value num))) 
        ((negative? num) 
        (loop rest (* value num))) 
        ((zero? num) 
        (loop rest (* value value))))))))) 

你應該研究它,看看它是如何工作的,然後使用完全不同的方法編寫自己的版本,如Jon關於使用compose的想法。:-)


編輯:我寫的功能可以進一步簡化:使用SRFI 1的fold,你可以這樣做:

(define (fun nums) 
    (define (step num value) 
    (cond ((positive? num) (+ value num)) 
      ((negative? num) (* value num)) 
      (else (* value value)))) 
    (lambda (x) 
    (fold step x nums))) 
+2

謝謝你的好話:-)看到兩個版本並排有趣是很有趣的:讓我想起SICP第4章中的一些解釋器與「編譯器」評估器。 – 2012-03-29 06:45:50

+0

事實上,這兩種方法比較有趣。實際上,'compose'本身也可以使用兩種方法來實現。這是我的「編譯器」式的方法來實現'compose':http://refactormycode.com/codes/836 – 2012-03-29 06:49:05

3

我認爲你非常接近解決方案。如果我是你,我會定義兩個輔助函數作爲buildseries的內部定義。一個是identity函數,它返回的參數不變。另一個是輔助函數compose,它需要兩個函數fg並返回一個計算其組成的新函數。這看起來像你的am助手,這也是「函數工廠」返回一個匿名函數,這取決於他們的論點。您可以考慮使用.來表示函數組合,將以下數學符號表示法翻譯爲Scheme:(f . g)(x) = f(g(x))。順便說一下,我認爲您對s的定義並不完全正確:它不需要是返回lambda的「函數工廠」,而只是一個簡單的函數x。它按書面形式工作,但由於您沒有對(外部)參數x做任何事情,所以您最好簡化爲(define (s x) (* x x))。然後在你的(= d 0)的情況下,你可以返回s,這本身就是一個非常好的函數值。

現在你需要考慮兩件事。首先,你的基本情況是什麼?當列表l爲空時,您返回什麼功能?接下來,如果l非空,那麼如何將列表中的first元素與列表中的rest以遞歸方式進行組合?

希望有幫助。讓我知道如果我能改善答案!

+0

是的,我不確定s的定義是否正確,但是當我測試它時它似乎起作用。我會試試這個。 – user1299108 2012-03-29 06:22:07

+0

希望它適合你!剛剛爲我自己嘗試過,我只是補充說,使用這種方法有一個稍微棘手的問題與「撰寫」的參數的順序... – 2012-03-29 06:32:26

+0

順便說一句,愛微妙的提示。 Nice touch – user1299108 2012-03-29 06:33:04

1

首先,你需要一個原函數bulider,需要一個數並作出對應功能:

(define (num->fun d) 
    (cond [(> d 0) (lambda (x) (+ x d))] 
     [(= d 0) (lambda (x) (* x x))] 
     [(< d 0) (lambda (x) (* x d))])) 

然後,您可以將此功能映射到數列表,它返回的功能清單,組成:

> (map num->fun '(4 -1 0)) 
=>'(#<procedure> #<procedure> #<procedure>) 

所以你可以用高階函數組成組成的功能此列表:

(apply compose (reverse (list-of-functions) 

要小心,組成以相反的順序撰寫功能,從而逆轉的功能列表在撰寫之前。 你可以把它弄出來:

(define (buildseries L) 
    (apply compose (reverse (map num->fun L)))) 
;try it: 
((buildseries '(4 -1 0)) 1);=>25