General pattern for selecting some elements of a list
This presentation is the property of its rightful owner.
Sponsored Links
1 / 12

general pattern for selecting some elements of a list PowerPoint PPT Presentation


  • 67 Views
  • Uploaded on
  • Presentation posted in: General

general pattern for selecting some elements of a list. This negatives example illustrates a general pattern: If you want a function which selects some elements from a list and drops others, you need a recursive function with two recursive conditions. (defun negatives(L) (cond ( (null L) ‘() )

Download Presentation

general pattern for selecting some elements of a list

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


General pattern for selecting some elements of a list

general pattern for selecting some elements of a list

This negatives example illustrates a general pattern:

If you want a function which selects some elements from a list and drops others, you need a recursive function with two recursive conditions.

(defun negatives(L) (cond ( (null L) ‘() )

( (< (first L) 0 )

(cons (first L) (negatives (rest L))) )

( t (negatives (rest L)) ) ))

One recursive condition conses the current first element to the answer that’s being built up, because it matches the criterion

The other recursive condition simply returns the answer built up for the rest of the list, “ignoring” the current first element


General pattern for selecting some elements of a list

Under the bonnet:Cons makes “cons cells”

Lists are implemented as building blocks called cons cells

A cons cell is a data structure with two fields:

a first fieldand a rest field

The first field contains a pointer to the first element of the list. The rest field points to the next cons cell in the list

The list ‘(doe ray mee) is really a chain of cons cells ending in a rest field with a nil


General pattern for selecting some elements of a list

Representing embedded lists

A lists with lists inside it:‘((karl lewis) is a (runner))


General pattern for selecting some elements of a list

Dotted pairs

Proper lists end in Nil but you can have lists which have another atom in the rest location.

> (cons ‘sonya ‘o-sullivan)

(sonya.o-sullivan)

These will print out as “dotted pairs”.


General pattern for selecting some elements of a list

first or CAR, rest or CDR

In the early days of Lisp, people used car (pronounced "CAR") and cdr ("could-a") instead of first and rest.

The only advantage car and cdr have is that you can combine them in a single function name; for example

(cadr L) means (car (cdr L)); same as (first (rest L))

(cddr L) means (cdr (cdr L)); same as (rest (rest L))

> (setf letters '(a (b (c))))

(A (B (C)))

> (caadr letters)

B

> (first (first (rest letters)))

B

Generally, except when we benefit from using one of these compound expressions, we will stick to FIRST and REST


General pattern for selecting some elements of a list

Operations on lists: Append

Cons takes an element (atom or list) and a list and puts the element first in a new list with the list argument as the rest.

>(cons ‘( 1 2 3) ‘(4 5 6) )

( (1 2 3) 4 5 6)

Append takes two lists (has to be two lists) and joins them together making a single list.

>(append ‘( 1 2 3) ‘(4 5 6) )

(1 2 3 4 5 6)

Append is a built-in function, like member. We can write append recursively, using cons. Lets see how.


Append as a recursive design example

Append as a recursive design example

Append is a function that joins two lists together.

Unlike cons, append is recursive .

Append takes two lists as arguments: (append A B)

We first need to figure out the stopping condition for append. We’ll focus on A in getting the stopping condition.

We ask: what is the simplest, smallest version of A so that, asked (append A B), we can return the correct answer straight away without having to do anything much?

>(append ‘() ‘(a b c) )

(a b c)

If asked to append an empty list A to any other list B, we can simply return the other list B without doing anything else.

(null A) is our stopping condition.


Append the recursive condition

Append: the recursive condition

Append takes two lists (append A B) and joins them together

We know the stopping condition is (null A).

What is the recursive condition going to be like?

Since the stopping condition is a test on A, we know that in the recursive condition we’re going to have to make the list A smaller on each recursive call (to eventually hit the stopping condition).

We also know that the recursive call will not reduce the size of the list B (since the stopping condition tests only A, not B).

So the recursive condition will contain the call

(append (rest A) B)

We will also need to do something with the bit of A that we’ve “left out” in this recursive call.


General pattern for selecting some elements of a list

Append: Combining the current element with the recursive answer

Suppose A is ‘(1 2 3), B is ‘(4 5 6) and we call (append A B)

We know that in executing (append A B) we will do the recursive call (append (rest A) B)

What will (append (rest A) B) return?

‘(2 3 4 5 6)

So what do we need to do to get the correct answer for (append A B)? We need to add the missing first element from A to the answer from (append (rest A) B).

Code for Append (using if rather than cond for a change):

(defun append(A B)

)

(if )

(null A)

B

(cons )

(first A)

(append )

(rest A)

B


Try tracing the execution of append yourself as in the factorial and countdown trace examples

Try tracing the execution of append yourself (as in the factorial and countdown trace examples)

Append is a built-in function in lisp, as are useful functions like member, replace, substitute etc. To understand recursion it’s good to know how they work.


Another recursive example reverse l

Another recursive example: (reverse L)

(reverse ‘(a b c d)) returns ‘(d c b a).

  • Stopping condition?

L is empty (null L)

  • Recursive call?

(reverse (rest L))

Suppose L = ‘(a b c d). What will (reverse (rest L)) return?

(d c b).

What do we need to do to ‘(d c b) to get ‘(d b c a)?

(append ‘(d c b) (list ‘a)) will return ‘(d b c a)

(defun reverse(L)

)

(cond ( )

)

(null L)

‘()

( t )

(append )

(reverse )

(rest L)

(list )

(first L)


One way to think about writing functions like these

One way to think about writing functions like these

Specifying the stopping conditions in a recursive function is very important; but it is usually easy.

It is harder to write the recursive conditions, especially to say how the answer from the recursive “smaller” call is combined with the “left-behind” part of the argument.

One trick: Take an example list argument. Assume the recursive call returns the correct answer for the “rest” part of that list. Figure out how to put that answer together with the left-behind “first” part of the list, to get the overall answer.

This “assume the smaller call is correct” approach is called induction.


  • Login