Functions

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0
Wiki Markup
{style}
cite{font-family:Courier New; font-style:normal}
{style}

h3. 

Function

...

data

...

type

...

In

...

Lisp,

...

a

...

function

...

is

...

a

...

data

...

type.

...

They

...

are

...

not

...

treated

...

any

...

differently

...

than

...

other

...

data

...

types.

...

To

...

pass

...

a

...

function

...

foo

...

as

...

an

...

argument,

...

you

...

give

...

it

...

the

...

prefix

...

#`

...

,

...

making

...

it

...

#`foo

...

.

...

The

...

parameter

...

listing

...

to

...

accept

...

a

...

function

...

does

...

not

...

need

...

any

...

special

...

identification.

...

The

...

function

...

can

...

then

...

(funcall

...

param)

...

to

...

execute

...

the

...

function.

...

}
Code Block
(defun applyFunc (function)

   (apply (car function) (cdr function) ) )


(applyFunc '(+ 1 1 1) )
{code}

For

...

another

...

example,

...

see

...

First-class

...

functions

...

.

Overloading

Functions may not be overloaded in Lisp. For instance, the following is illegal:

Code Block
(defun plus(x y)
   (+ x y) )

(defun plus(x y z)
 (+ x y z) )

{code}

This

...

example

...

shows

...

that

...

the

...

built-in

...

function

...

+

...

can

...

accept

...

any

...

number

...

of

...

arguments.

...

This

...

is

...

not

...

an

...

example

...

of

...

overloading,

...

but

...

instead

...

an

...

instance

...

of

...

allowing

...

for

...

an

...

arbitrary

...

number

...

of

...

parameters.

...

Lambda

...

Expressions

...

Sometimes

...

we

...

want

...

to

...

create

...

a

...

function

...

that

...

is

...

used

...

as

...

an

...

argument

...

but

...

never

...

called

...

on

...

its

...

own.

...

Such

...

a

...

function

...

does

...

not

...

need

...

a

...

name

...

and,

...

once

...

bound

...

to

...

a

...

variable,

...

is

...

only

...

used

...

in

...

the

...

context

...

of

...

the

...

variable.

...

Lisp

...

has

...

lambda

...

expressions

...

for

...

these

...

situations.

...

For

...

instance,

...

if

...

a

...

sorting

...

routine

...

requires

...

a

...

comparison

...

function

...

as

...

an

...

argument,

...

you

...

may

...

want

...

to

...

use

...

a

...

common

...

one

...

such

...

as

...

<,

...

or

...

you

...

may

...

want

...

to

...

define

...

your

...

own.

...

If

...

you

...

define

...

your

...

own,

...

you

...

do

...

not

...

need

...

to

...

write

...

a

...

defun

...

for

...

it

...

because

...

you

...

only

...

need

...

it

...

to

...

sort

...

lists

...

in

...

this

...

one

...

location.

...

You

...

can

...

write

...

a

...

lambda

...

expression

...

to

...

define

...

the

...

function

...

right

...

where

...

you

...

need

...

it.

...

The

...

syntax

...

is

...

to

...

follow

...

the

...

symbol

...

lambda

...

by

...

a

...

list

...

of

...

the

...

parameters

...

and

...

then

...

the

...

body

...

of

...

the

...

function.

...

For

...

example:

...

(lambda

...

(x)

...

(*

...

x

...

x))

...

or

...

(lambda

...

(x

...

y)

...

(cons

...

x

...

(list

...

y)))

...

.

In the following code snippet, we use the built-in sort function which takes a list and comparison function as arguments. In the first line, we call it with the built-in operator < to sort the list in ascending order. The second line will also sort the list in ascending order, but use a lambda expression to express our intentions. This is not useful, but it demonstrates the possibilities. You can create any relation, though it should satisfy transitivity, reflexiveness, and antisymmetry so that the list can in fact be ordered.

Code Block
(sort listToSort #'<)

(sort listToSort #'(lambda (a b) (if (< a b) t '())))
{code}

h3. Local Functions

We have previously mentioned that ??let?? is a special form which allows you to create local variables.  Lisp also allows you to make local _functions_.  The corresponding operator is ??flet?? (Function LET).  A drawback of ??flet?? is that you cannot call one local function from another.  The operator ??labels??, on the other hand, does permit this.

Local functions are useful because they allow one function to contain all of its logic, while at the same time modularizing it.  This is particularly helpful to implement tail-recursion, which is more efficient than other varieties of recursion but often needs an extra parameter.  The primary function may have only the parameters one would expect, and it can define a local tail-recursive function, which it calls.

The following example merges two sorted lists (as in merge-sort).  Notice that ??revlist?? uses tail recursion with local functions. The option on the left uses nested ??flet??, and the right uses ??labels??.  We could replace the ??flet?? with ??labels??, but not vice versa because ??revlist?? uses ??rev-util??.

Local Functions

We have previously mentioned that let is a special form which allows you to create local variables. Lisp also allows you to make local functions. The corresponding operator is flet (Function LET). A drawback of flet is that you cannot call one local function from another. The operator labels, on the other hand, does permit this.

Local functions are useful because they allow one function to contain all of its logic, while at the same time modularizing it. This is particularly helpful to implement tail-recursion, which is more efficient than other varieties of recursion but often needs an extra parameter. The primary function may have only the parameters one would expect, and it can define a local tail-recursive function, which it calls.

The following example merges two sorted lists (as in merge-sort). Notice that revlist uses tail recursion with local functions. The option on the left uses nested flet, and the right uses labels. We could replace the flet with labels, but not vice versa because revlist uses rev-util.

Wiki Markup
{table}{tr}{td}
{code}
;; merges two ordered lists together
(defun smerge (left right list)
  (flet (( revlist (data)
          (flet ((revutil (data revdata)
            (if (eq data '())
                revdata
                (revutil (cdr data)
                        (cons (car data) revdata)) )))
        (revutil data '()) )))
    (if (or (eq left '()) (eq right '()))
        (append (revlist list) left right)
        (if (<= (car left) (car right))
            (smerge (cdr left) right
                     (cons (car left) list))
            (smerge left (cdr right)
                    (cons (car right) list)) ) ))
{code}{td}{td}{code}
(defun smerge (left right list)
  (labels ( (revlist (data)
             (revutil data '()) )
          (revutil (data revdata)
            (if (eq data '())
                revdata
                (revutil (cdr data)
                         (cons (car data) revdata))
            )))
     (if (or (eq left '()) (eq right '()))
        (append (revlist list) left right)
        (if (<= (car left) (car right))
            (smerge (cdr left) right
                 (cons (car left) list))
            (smerge left (cdr right)
                 (cons (car right) list))
         ) ))
{code}{td}{tr}{table}