Page 1 of 1

how do I run this procedure?

Posted: Thu Oct 20, 2016 2:37 pm
by NewToLisp
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
by sylwester
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.