linuxfish
linuxfish

Reputation: 89

passing function as a parameter to another function in scheme

Basicly,what I want to do is this:

I have a function square(x) (define (square x) (* x x))(f(x)=x*x),and another function mul_two (define (mul_two x) (* 2 x))(g(x)=2*x), I want to construct a new function based on the above two functions, what the new function does is this: 2*(x*x)(p(x)=g(f(x))), how can I write this new function in scheme? Although its a pretty straight thing in mathmatical form I'm totally stuck on this .

Upvotes: 0

Views: 5834

Answers (3)

nicky_zs
nicky_zs

Reputation: 3773

(define (new_fun x) (mul_two (square x)))

EDIT:

(define (square x) (* x x))
(define (mul_two x) (* 2 x))

(define (new_fun fun1 fun2) (lambda (x) (fun2 (fun1 x))))

((new_fun square mul_two) 10)

And you will get 200. (10 * 10 * 2)

Also, you can implement a general purpose my-compose function just as the compose in racket:

(define (my-compose . funcs)
  (let compose2
    ((func-list (cdr funcs))
     (func (lambda args (apply (car funcs) args))))
    (if (null? func-list)
      func
      (compose2
        (cdr func-list)
        (lambda args (func (apply (car func-list) args)))))))

And you can obtain new-fun by:

(define new-fun (my-compose mul_two square))

Upvotes: 3

Sylwester
Sylwester

Reputation: 48765

In #!racket (the language) you have compose such that:

(define double-square (compose double square))

Which is the same as doing this:

(define (double-square . args)
   (double (apply square args))) 

If you want to use Scheme (the standard) you can roll your own:

#!r6rs
(import (rnrs))

(define (compose . funs)
  (let* ((funs-rev (reverse funs))
         (first-fun (car funs-rev))
         (chain (cdr funs-rev)))
    (lambda args
      (fold-left (lambda (arg fun) 
                   (fun arg))
                 (apply first-fun args)
                 chain))))

(define add-square (compose (lambda (x) (* x x)) +))
(add-square 2 3 4) ; ==> 81

Upvotes: 0

Óscar López
Óscar López

Reputation: 236112

The usual way to do what you're asking is by using compose, which according to the linked documentation:

Returns a procedure that composes the given functions, applying the last proc first and the first proc last.

Notice that compose is quite powerful, it allows us to pass an arbitrary number of functions that consume and produce any number of values. But your example is simple to implement:

(define (square x)   ; f(x)
  (* x x))

(define (mul_two x)  ; g(x)
  (* 2 x))

(define p ; g(f(x))
  (compose mul_two square))

(p 3) ; same as (mul_two (square 3))
=> 18

If for some reason your Scheme interpreter doesn't come with a built-in compose, it's easy to code one - and if I understood correctly the comments to the other answer, you want to use currying. Let's write one for the simple case where only a single value is produced/consumed by each function, and only two functions are composed:

(define my-compose ; curried and simplified version of `compose`
  (lambda (g)
    (lambda (f)
      (lambda (x)
        (g (f x))))))

(define p ; g(f(x))
  ((my-compose mul_two) square))

(p 3) ; same as (mul_two (square 3))
=> 18

Upvotes: 3

Related Questions