Page 1 of 1

### how do I run this procedure?

Posted: Thu Oct 20, 2016 2:37 pm
I am new to Lisp and im trying to define a function.
This is the code i managed to write:
(define (func n)
(lambda (n)
(cond ((= n 0) 0) ;;If n=0, return 0
((= n 1) 2) ;;If n=1, return 2
((= n 2) 37) ;;If n=2, return 37
((= n odd?) (+ (func (- n 3)) 1) ;;If n is odd, return f(n-3) + 1
(else (+ (func (- (/ n 2) 1)) 7))))) ;;Else return f((n/2) - 1) + 7

But when I make a call, it doesn't compute it. For example, when i type (func 17), it returns "#<procedure>". So how do I make it compute a call?

### Re: how do I run this procedure?

Posted: Tue Oct 25, 2016 6:22 am
Your procedure returns a new procedure. In Scheme you have this way of making a variable:

Code: Select all

``````(define test 10)
(define test-proc (lambda (n) (+ n n))
``````
Then you have this abbrivation for the special case where the value is a procedure:

Code: Select all

``(define (test-proc n) (+ n n))``
It's the same as the other expression making the variable test-proc. If you look at your definition you see that you do both. So in reality you have.

Code: Select all

``````(define proc
(lambda (n)         ; this is the first layer. The procedure the variable proc will become
(lambda (n) ...)  ; this is the procedure the procedure proc will return
``````
Looking at the arguments you have n both places so the previous will definitely be overshadowed by the second. Perhaps you didn't want it to return a new procedure? In that case just remove one:

Code: Select all

``````(define (func n)
(cond ((= n 0) 0)                         ;;If n=0, return 0
((= n 1) 2)                         ;;If n=1, return 2
((= n 2) 37)                        ;;If n=2, return 37
((odd? n) (+ (func (- n 3) 1)))     ;;If n is odd, return f(n-3) + 1
(else (+ (func (- (/ n 2) 1)) 7)))) ;;Else return f((n/2) - 1) + 7
``````
I noticed you are checking if the procedure odd? is the same number as n. This will never work as odd? is not a number at all but a procedure that checks if it's argument is an odd number. (odd? n) perhaps what you wanted?
In DrRacket, after pressing CTRL+i, to fix identation, I noticed the identation was off and thus that means your parentheses most likely are not correct and your program will fail (or worse, do something else than you think).
I changed it so that else comes on the level of cond. Now you can call it like this:

Code: Select all

``````(func 10) ; ==> 16
``````
As for an example of procedures that return procedures. Imagine you have a procedure that sums two squares and divides:

Code: Select all

``````(define (sum-square a b)
(+ (* a a)
(* b b)))

(define (divide-square a b)
(/ (* a a)
(* b b)))
``````
Now you see a pattern there so you must be able to abstract that so it becomes smaller:
Now you could do this:

Code: Select all

``````(define (proc-square proc a b)
(proc (* a a)
(* b b)))

;; new version of sum-square
(define (sum-square a b)
(proce-square + a b))

;; divide the square version
(define (divide-square a b)
(proc-square / a b))
``````
But you could also make use of closures and do it like this:

Code: Select all

``````(define (proc-square proc)
(lambda (a b)
(proc (* a a)
(* b b))))

;; new version of sum-square
(define sum-square (proce-square +))

;; divide the square version
(define divide-square (proc-square /))
``````
In this case it's a matter of taste, but in procedures where you need to use map or fold and need a procedure this wuld be the simplest and you don't even need to use define but pass it directly.