220 likes | 332 Views
Lists and Recursion. Jeremy Johnson Kurt Schmidt Drexel University. Lists: L = (x 1 … x n ). A list is either empty () [same as nil] or made up of Cons cells consp : All → Boolean cons : All × List → Cons (cons x L) = (x x 1 … x n ) first : Cons → All (first (cons x L)) = x
E N D
Lists and Recursion Jeremy Johnson Kurt Schmidt Drexel University
Lists: L = (x1 … xn) • A list is either empty () [same as nil] or made up of Cons cells • consp : All → Boolean • cons : All × List → Cons • (cons x L) = (x x1 … xn) • first : Cons → All • (first (cons x L)) = x • rest : Cons → List • (rest (cons x L)) = L
List Examples • (list x1 … xn) [macro – variable # of args] • (cons x1 (cons x2 … (cons xn nil)…)) • (consp ()) = nil • (cons 1 ()) = (1) • (consp (cons 1 ())) = t • (cons 1 (cons 2 (cons 3 ()))) = (1 2 3) • (list 1 2 3) = (1 2 3) • (cons (cons 1 ()) ()) = ((1))
Exercise • How do you construct the list ((1) 2)?
Exercise • How do you construct the list ((1) 2)? • (cons 1 ()) = (1) • (cons 2 ()) = (2) • Want (cons x y) where x = (1) and y = (2) • (cons (cons 1 ()) (cons 2 ())) = ((1) 2) • Test this (and try additional examples) in ACL2 REPL
More About cons • A cons cell contains two fields • first [also called car] • rest [also called cdr] • For a list the rest field must be a list • Generally both fields of a cons All • (cons 1 2) = (1 . 2) • Called a dotted pair
List Processing • Recursive Definition • List : nil | cons All List • Process lists using these two cases and use recursion to recursively process lists in cons • Use first and rest to access components of cons
Recursion and listp1 (defunc listp (l) :input-contract t :output-contract (booleanp (listp l)) (if (consp l) (listp (rest l)) (equal l () ))) 1. listp is a built-in function in the full ACL2 mode
Incorrect listp • Nonterminating • ACL will not accept functions it can not prove terminate (defunclistp (a) :input-contract t :output-contract (booleanp (listp a)) (if (consp a) (listp a) (equal a nil)))
Version 2 of listp (defunc listp (l) :input-contract t :output-contract (booleanp (listp l)) (if (equal l nil) t (if (consp l) (listp (rest l)) nil)))
Version 3 of listp (defunc listp (l) :input-contract t :output-contract (booleanp (listp l)) (cond ((equal l nil) t) ((consp l) (listp (rest l))) nil))
Length1,2 (defun length (l) (if (equal l nil) 0 ( ) )) 1: defun is used instead of defunc since ACL can not prove termination and contract satisfaction without induction, which the bare bones mode does not support 2. Length is a built-in function in the full ACL2 mode
Length1,2 (defun length (l) (if (equal l nil) 0 (+ 1 (length (rest l))) )) • The recursive function can be “thought of” as a definition of length 1: defun is used instead of defunc since ACL can not prove termination and contract satisfaction without induction, which the bare bones mode does not support 2. Length is a built-in function in the full ACL2 mode
Member1 (defun member (x l) (cond ((equal l nil) nil) ( ) ( ))) 1. Member is a built-in function in the full ACL2 mode
Member1 (defun member (x l) (cond ((equal l nil) nil) ((equal x (first l)) t) ((member x (rest l) ))) 1. Member is a built-in function in the full ACL2 mode
Member1 (defun member (x l) (cond ((equal l nil) nil) ((equal x (first l)) t) ((member x (rest l))))) 1. Member is a built-in function in the full ACL2 mode
Append1 (defun append (x y) ) • (append ‘(1 2 3) ‘(4 5 6)) (1 2 3 4 5 6) • Recurse on the first input 1. Append is a built-in function in the full ACL2 mode
Append1 (defun append (x y) (if (equal x nil) y (cons (first x) (append (rest x) y)))) • Recurse on the first input 1. Append is a built-in function in the full ACL2 mode
Reverse1 (defun reverse (l) ) • (reverse ‘(1 2 3)) (3 2 1) 1. Reverse is a built-in function in the full ACL2 mode
Reverse1 (defun reverse (l) (if (equal l nil) nil (append (reverse (rest l)) (cons (first l) nil)))) 1. Reverse is a built-in function in the full ACL2 mode
Numatoms (defun atomp (x) (not (consp x))) (defun numatoms (x) (cond ((equal x nil) 0) ((atomp x) 1) ((+ (numatoms (first x)) (numatoms (rest x))))))
Shallow vs Deep Recursion • Length and Member only recurse on the rest field for lists that are conses • Such recursion is called shallow – it does not matter whether the lists contain atoms or lists • (length ‘((1 2) 3 4)) = 3 • Numatoms recurses in both the first and rest fields • Such recursion is called deep – it completely traverses the list when elements are lists • (numatoms ‘((1 2) 3 4)) = 4