Functions


Purpose

Functions are expressions that take arguments and return a value. They both reduce the complexity of your program and increase its readability, by abstracting conceptually related series of commands.

Usage

Functions are created using "define".

Define takes two arguments: the first is a list containing the name of the function and the names of its arguments. Define's second argument is the function body, illustrated below.

Examples

A simple example: creating a function which adds one to any number.
  ox --> (define (add-one x) 
           (+ x 1)
	  )
  add-one
  ox --> (add-one 5)
  6
The define expression returns a function which takes one argument, "x" and returns x+1.


The function body, "(+ x 1)" in the previous example, can be arbitrarily complex, if "begin" is used:
  ox --> (define (count-to-n n)
           (begin
             (define counter 0)
             (while (<= counter n)
               (begin
                 (print counter)
                 (set! counter (+ counter 1))
                )
              )
             (print "All done!")
            )
          )
  count-to-n
  ox --> (count-to-n 3)
  0
  1
  2
  3
  "All done!"

The primary way we'll use functions is to abstract objects. Rather than including several lines of code every time we want to create objects with various traits, we can create functions that we can call when needed:
  (define (special-skull)
    (separator
      (color (vec3 0 0 1))
      (surface "wood")
      (displacement "bumpy")
      (accad-object "skull.obj")))

  (define (ground)
    (separator
      (color (vec3 5 3 2))
      (surface "marble")
      (displacement "cloth")
      (rotate 90 x-axis)
      (disk 'radius 20)))
We can then call the function when we want the object, making the code much more readable:
 (world 
  (ground)
  (translate 0 1 0)
  (special-skull))
It is much simpler to see at a glance that we have a skull above the ground, than if we had included the eleven or so lines above, inside world.


Functions are basic "objects" just like numbers, symbols, strings and lists. We have generally defined functions by saying things like:
  (define (add1 x)
    (+ 1 x))
But remember that just as we can assign a number as the value of a variable as in:
  (define myNumber 5)
we can also assign a function as the value of a variable:
  (define myFunc add1)
What we would like to be able to do, is to define a function with out giving it a name, just as we can invoke a number, or a symbol without assigning it to a variable. To do this, we use a construct called lambda. To define the function we have assigned to "myFunc" above, we would say:
  (lambda (x) (+ 1 x))
This creates a function (with no name) that takes one argument, "x", and returns the value of (+ 1 x) when invoked.

To redo our previous assignment, we could now say:

  (define myFunc (lambda (x) (+ 1 x)))
Which let's us then do:
  ox --> (myFunc 5)
  6
This lets us maintain lists of functions, and pass functions as arguments to other functions, without having to define names that we'll never use.

More importantly however, it lets us use and understand "object-oriented programming".

(define (create-bird)

  (let (
	(name "Bird")
	(position (vec3 0 0 0))
        (bird-color (vec3 1 1 1))
        (direction (vec3 0 0 1))
	(speed 1)
	)

    (define (set-name! n) (set! name n))
    (define (set-position! p) (set! position p))
    (define (set-color! c) (set! bird-color c))
    (define (set-direction! d) (set! direction d))
    (define (set-speed! s) (set! speed s))

    (define (draw)
      (separator
       (translate position)
       (sphere))  ; or whatever you want your bird geometry to be...
      )

    (lambda (message)
      (cond
       ((eq? message 'set-name!) set-name!)
       ((eq? message 'set-position!) set-position!)
       ((eq? message 'set-color!) set-color!)
       ((eq? message 'set-direction!) set-direction!)
       ((eq? message 'set-speed!) set-speed!)
       ((eq? message 'draw) (draw))
       (else (error "Object: unknown message" message))))))

(define my-bird (create-bird))

((my-bird 'set-position!) (vec3 1 1 1))
((my-bird 'set-color!) (vec3 1 0 0))
(my-bird 'draw)

Return to Scheme Introduction
mrl