2012-03-29 60 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