Predicates & Logic

Download Report

Transcript Predicates & Logic

Control in LISP
More on Predicates & Conditionals
Equality Tests

LISP provides multiple equality tests
– EQUAL and =
– EQL and EQ

Serve different purposes
– they give different answers in some cases
Equal and =
EQUAL is for general comparisons
 = is used for numeric comparisons

– an error to use = with non-numbers

= does type conversion; EQUAL does not
– (= 15 15.0) returns T
– (equal 15 15.0) returns NIL
Eq

EQ is “pointer” equality
– are these “two” objects pointing to the same
hunk of memory
T if same atom or same variable
 Maybe T if same number & type

> (list (eq ‘a ‘a) (eq ‘(a) ‘(a)))
(T NIL)
Eq and SetF
> (setf a ‘(1 2 3))
> (setf b ‘(1 2 3))
> (setf c a)
> (list (eq a ‘(1 2 3)) (eq a a) (eq a b) (eq a c))
(NIL T NIL T)

A and B are different, but A and C are same
– even tho’ they all look exactly the same
Eql and Eq
EQL is just like EQ except for numbers
 A number is always EQL to itself

– it may not be EQ to itself
– neither EQ nor EQL if different types
> (list (eql 100 100) (eql 100 100.0) (eq 100 100))
(T NIL T) or
(T NIL NIL)
Equal

EQUAL is general purpose
– except for numbers it’s what you’d expect
> (setf a ‘(1 2 3))
> (setf b ‘(1 2 3))
> (list (equal a ‘(1 2 3)) (equal a a) (equal a b))
(T T T)
> (list (equal 1 1.0) (equal a ‘(1.0 2.0 3.0)))
(NIL NIL)
Equal is Equal

EQUAL goes all the way down
– lists with lists treated properly
> (equal ‘(1 (2 (3 4) (5 6))) ‘(1 (2 (3 4) (5 6))))
T
> (equal ‘(1 2 (3 4)) ‘(1 2 3 4))
NIL
Testing for Equality
Use EQUAL if need to compare lists
 Use EQ or EQL for atoms/integers

– more efficient than equal

Use = for general numbers
– only one that equates integers with floats
Exercise

True, false, either or error:
(eq ‘a ‘a)
(eq 10 10)
(eq 10 10.0)
(eq ‘(10) ‘(10.0))
(equal 10 10.0)
(equal ‘(10) ‘(10.0))
(eql ‘a ‘a)
(eql 10 10)
(eql 10 10.0)
(eql ‘(10) ‘(10.0))
(= 10 10.0)
(= ‘(10) ‘(10.0))
Data Type Predicates

Can test an object to see whether it’s a
particular type
– ATOM, NUMBERP, SYMBOLP, LISTP
– (no P at the end of ATOM)
Numbers and symbols are also atoms
 NIL is an atom and a list

Testing for Type
> (list (atom ‘a) (numberp ‘a) (symbolp ‘a) (listp ‘a))
(T NIL T NIL)
> (list (atom 5) (numberp 5) (symbolp 5) (listp 5))
(T T NIL NIL)
> (list (atom ()) (numberp ()) (symbolp ()) (listp ()))
(T NIL T T)
> (list (atom ‘(a 1)) (numberp ‘(a 1))
(symbolp ‘(a 1)) (listp ‘(a 1)))
(NIL NIL NIL T)
Exercise

Evaluate:
> (setf a ‘(+ 2 5))
> (list (atom ‘a) (numberp ‘a))
> (list (atom a) (numberp a))
> (list (atom (+ 2 5)) (numberp (+ 2 5)))
> (list (listp ‘a) (listp a) (listp (+ 2 5)))
> (list (symbolp ‘a) (symbolp a) (symbolp (+ 2 5)))
Number Tests

Simple tests on numbers
– ZEROP, PLUSP, MINUSP, EVENP, ODDP

All do what you’d expect, but
– errors if not given numbers
– errors if given more than one argument
> (list (zerop 0) (plusp 1) (minusp 2) (evenp 3))
(T T NIL NIL)
Compound Conditions

LISP provides functions for logical
combination of conditions
– AND, OR, NOT

Can be used anywhere a condition is
required
Logical And

All arguments must be true (i.e. non-NIL)
– returns NIL if one argument is NIL
– returns last argument if all non-NIL
> (and (member ‘a ‘(d a d)) (member ‘o ‘(m o m)))
(O M)
> (and (member ‘a ‘(d a d)) (member ‘b ‘(m o m)))
NIL
Exercise

Evaluate the following:
> (and (member ‘a ‘(d a d)) (member ‘u ‘(b u d)))
> (and (member ‘a ‘(d a d)) (atom ‘(b u d)))
> (and (eq ‘a ‘a) (eql ‘a ‘a) (equal ‘a ‘a))
> (and (eql 10 10.0) (= 10 10.0))
> (and (atom nil) (listp nil) (numberp nil))
> (and (numberp 10) (numberp 20) (+ 10 20))
Logical Or

One argument must be non-NIL
– returns NIL if all are NIL
– returns first non-NIL if one is non-NIL
> (or (member ‘a ‘(d a d)) (member ‘b ‘(m o m)))
(A D)
> (or (member ‘a ‘(d u d)) (member ‘b ‘(m i m)))
NIL
Exercise

Evaluate the following:
> (or (member ‘a ‘(d a d)) (member ‘u ‘(b u d)))
> (or (member ‘a ‘(b u d)) (atom ‘(b u d)))
> (or (eq ‘a ‘a) (eql ‘a ‘a) (equal ‘a ‘a))
> (or (eql 10 10.0) (= 10 10.0))
> (or (atom ‘a) (listp ‘a) (numberp ‘a))
> (or (numberp 10) (numberp 20) (+ 10 20))
Logical Not

Reverses its one argument
– returns T if argument is NIL
– returns NIL if argument is non-NIL
> (not (member ‘a ‘(d a d)))
NIL
> (not (member ‘b ‘(m o m)))
T
Exercise

Evaluate the following:
> (not (member ‘a ‘(d a d)))
> (not (member ‘u ‘(b a d)))
> (not (or (member ‘a ‘(d a)) (member ‘u ‘(u p))))
> (not (and (member ‘a ‘(d a)) (member ‘u ‘(u p))))
> (or (not (atom ‘a)) (not (listp ‘a)))
> (and (not (evenp 3)) (or (oddp 8) (zerop 0)))
Exercise

Write a function that takes an atom and two
lists, and says how many of the lists the
atom is in: ‘none, ‘one, or ‘both
> (two-member ‘a ‘(s a d) ‘(d a d))
BOTH
> (two-member ‘o ‘(c a l m) ‘(m o m))
ONE
“Short-Circuit” Evaluation

AND & OR are special forms
– only evaluate arguments until answer known
– can “guard” conditions
> (defun eqn (M N)
(and (numberp N) (numberp M) (= N M)))
> (eqn 15 15.0)
T
> (eqn ‘a ‘a)
NIL
Short Circuits
> (eqn 15 15.0)
(and
(numberp 15) => T
(numberp 15.0) => T
(= 15 15.0) => T
) => T
> (eqn ‘a ‘a)
(and
(numberp ‘a) => NIL
) => NIL

Doesn’t do:
(numberp ‘a) => NIL
(= ‘a ‘a) => ERROR
AND stops as soon as it sees a NIL
Short Circuits

OR stops as soon as it sees non-NIL
(setf L ‘(a))
(or (null L) (= (length L) 1) (eq (first L) (second L))
(or
(null ‘(a)) => NIL
(= (length ‘(a)) 1) => (= 1 1) => T
) => T
Does not compare (first L) = a
with (second L) = NIL
Exercise

Write “safe” versions of EVENP & PLUSP
– don’t give errors when called with non-numbers
Version 1: use if, when or unless
 Version 2: use and, or or not

Case

CASE special form simplifies CONDs
– all conditions (except else) involve checking
one object against others
> (defun fib (N)
(cond ((= N 0) 1)
((= N 1) 1)
(T (+ (fib (– N 1)) (fib (– N 2))))))
FIB
Case

CASE is a special form
– first argument is evaluated
– remaining arguments are not
> (defun fib (N)
(case N
(0
1)
(1
1)
(T
(+ (fib (– N 1)) (fib (– N 2))))))
Case Cases
Cases appear a (LABEL FORM) pairs
 First matching case is selected

– the form paired with it is evaluated & returned

Matching:
– if LABEL is T or OTHERWISE, match
– if LABEL is an atom, use EQL to compare
– if LABEL is a list, use member on that list
Compound Case
> (defun fib2 (N)
(case N
((1 2) 1)
(T
(+ (fib2 (– N 1)) (fib2 (– N 2))))))
Calls (member N ‘(1 2)) for first case
 Just succeeds for second case

Exercise

Write a function to expand three-letter
abbreviations for days of the week to the
full day name. Use a case statement.
– return NIL if the day is not recognized
> (day-full-name ‘wed)
WEDNESDAY
Exercise

Write a function with case statement to
return the number of days in a month (given
as a 3-letter abbr.). Ignore leap years.
– Thirty days hath September,
April, June and November.
All the rest have thirty-one,
Save February all alone,
Which hath twenty eight days clear, & so on
Next Time

More Control in LISP
– Chapters 4, 5 & 7