A function builder in scheme

2019-08-07 14:01发布

A function I'm supposed to build is supposed to take in a list of numbers as a parameter, and give a single function as an output that does as follows: If the number in the list is a positive number, add it, if it is negative multiply by it, and if it is 0, square the number.

For example, if I pass in (4 -1 0), it should return a function that takes in a single parameter, adds 4 to it, multiplies it by -1, squares it, and returns that.

I think I'm on the right track, but I'm getting seriously confused at this point. I'm not necessarily looking for a solution, but any help getting there would be amazing. Here's what I have so far:

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

I don't know how to build a function that is a composite of other functions... Just feeling lost here.

3条回答
Root(大扎)
2楼-- · 2019-08-07 14:16

I think you're pretty close to a solution. If I were you, I would define two more helper functions as inner definitions of buildseries. One would be an identity function that just returns its argument unchanged. The other would be a helper function, compose, that takes two functions f and g and returns a new function that computes their composition. This will look something like your a and m helpers, which are also "function factories" returning an anonymous function which depends on their argument. You might think about translating the following math-ish notation, using . to represent function composition, into Scheme: (f . g)(x) = f(g(x)).

By the way, I think your definition of s is not quite right: it doesn't need to be a "function factory" that returns a lambda, but simply a plain function of x. It will work as written, but since you're not doing anything with the (outer) argument x you might as well simplify it to (define (s x) (* x x)). Then in your (= d 0) case you can just return s, which is a perfectly good function value itself.

Now you need to think about two things. First, what is your base case? What function do you return when the list l is empty? Next, when l is non-empty, how will you combine whatever you do with the first element of the list with whatever you do, recursively, with the rest of the list?

Hope that's helpful. Let me know if I can improve the answer!

查看更多
Animai°情兽
3楼-- · 2019-08-07 14:25

Jon's answer is very good. You should try to implement it as much as you can. If you need to, you can also refer to my answer here (which doesn't follow Jon's approach since I wrote most of my answer before he posted his):

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

You should study it to see how it works, then write your own version using a completely different approach, like Jon's idea about using compose. :-)


Edit: The function I wrote can be simplified further: using SRFI 1's fold, you can do this:

(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)))
查看更多
欢心
4楼-- · 2019-08-07 14:36

first,you need a primitive function bulider that takes a number and make a correspondence function:

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

then,you can map this function to a list of number,it returns a list of functions to be composed:

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

so you can use high order function compose to compose this list of functions:

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

be careful,the compose compose functions in a reversed order,so reverse the list of function before compose. you can abstruct that out:

(define (buildseries L)
  (apply compose (reverse (map num->fun L))))
;try it:
((buildseries '(4 -1 0)) 1);=>25
查看更多
登录 后发表回答