how do I run this procedure?

Discussion of Scheme and Racket
NewToLisp
Posts: 1
Joined: Thu Oct 20, 2016 2:04 pm

how do I run this procedure?

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?

sylwester
Posts: 133
Joined: Mon Jul 11, 2011 2:53 pm

Re: how do I run this procedure?

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.
I'm the author of two useless languages that uses BF as target machine.
Currently I'm planning a Scheme compiler :p