This action might not be possible to undo. Are you sure you want to continue?
It was invented by John McCarthy during the late 1950’s, shortly after the development of FORTRAN, LISP is particularly suited for AI programs because of its ability to process symbolic information effectively. It is a language with a simple syntax, with little or no data typing and dynamic memory management. There are several dialects of LISP including FRANZLISP, INTERLISP,MACLISP, QLISP, SCHEME and COMMON LISP. The COMMON LISP version is a recent attempt to standardize the language to make it more portable and easier to maintain.
LISP has become the language of choice for most AI practitioners. It was practically unheard of outside the research community until AI began to gain some popularity ten to fifteen years ago. Since then, special LISP processing machines have been built and its popularity has spread to many new sectors of business and government. In this chapter we give a summary of the important features of LISP and briefly introduce PROLOG and other AI languages.
3.2 Introduction to LISP
• • •
LISP is the oldest computer programming language It has the ability to process symbolic information effectively It is a language with simple syntax, with little or no data typing and dynamic memory management
3.3 Syntax and numeric functions • • • • Lisp operates on forms. Each Lisp form is either an atom or a list of forms. Atoms are numbers, strings, symbols and some other structures. When Lisp is forced to evaluate the form it looks whether it's an atom or a list. If it's an atom then its value is returned (numbers, strings and other data return themselves, symbols return their value).
If the form is a list Lisp looks at the first element of the list - its car. The car of that list should be a symbol or a lambda-expression.
If it's a symbol Lisp takes its function and executes that function with the arguments taken from the rest of the list.
Example: (+ 1 2 3) returns 6. Symbol "+" is associated with the function + that performs the addition of its arguments. (+ 1 (+ 2 3) 4) returns 10. The second argument contains a form and is evaluated before being passed to the outer +.
The Basic building blocks of LISP are atom, list and the string An atom is a number or string of contiguous characters, including numbers and special characters. Ex: this-is-a-symbolic-atom, kill, a1234, item#4
A list is a sequence of atoms or list enclosed within parentheses. Ex: (this is a list), (x(x y) z pq), ( ), (jan, feb, mar)
A string is a group of characters enclosed in double quotation marks. Ex: “this is a string”, “what is your name”
The top elements of the list (a b (c, d) e (f)) are a, b, (c d), e and (f). The elements c and d are the top elements of the sublist (c d)
• • •
Atoms, lists and strings are called symbolic expressions or s-expressions LISP programs run either on an interpreter or as compiled code The interpreter examines source programs in a repeated loop called the read-evaluate-print loop. This loop reads the program code, evaluates it and prints the values returned by the program
The interpreter signals to accept code for execution by printing a prompt such as the - > Example: To find the sum of three numbers 2, 3, 4 ->(+ 2 3 4) 9 ->
LISP uses prefix notation, and the + symbol is the function name for the sum of the arguments that follow
The read-evaluate-print loop reads the expression, evaluates it and prints the value returned (9)
Example: The mathematical expression (50 * 9 / 5) + 32 -> (+ (* ( / 9 5) 50) 32) 122
-> • • Each function call is performed in the order in which it occurs within the parenthesis To compute the sum, the argument (* ( / 9 5) 50) must first be evaluated. This requires that the product of 50 and 9 / 5 be computed, which in turn requires that the quotient 9 / 5 be evaluated. The embedded function (/ 9 5) returns the quotient 1.8 to the multiply function to give (* 1.8 50). This is then evaluated and the value 90 is returned to the sum function to give (+ 90 32). The final result is the sum 122 returned to the read-evaluateprint loop for printing • • The basic numeric operations are +, -, * and /. Arguments may be integers or real values Examples of function calls and the results returned are listed below (+ 3 5 8 4) (- 10 12) (/ 25 2) • • • -2 12.5 20
The letter t signifies logical true and nil signifies logical false NIL is also the same as the empty list ( ) Example: ->t T ->NIL NIL
3.4 Basic list manipulation functions in LISP • • • • • The atom or list is represented with a single quotation mark. E.g.: ‘man, ‘(a b c d) The quotation mark informs the interpreter that the atom or list should not be evaluated Variables in Lisp are symbolic atoms Symbolic atoms may be assigned values i.e. bound to values with the function setq setq takes two arguments The first argument must be a variable. It is never evaluated and should not be in quotation marks • Second argument is evaluated and the result is bound to the first argument
When variables are evaluated, they return the last value bound to them
Some of the examples are setq are ->(setq x 10) 10 ->x 10 ->(setq x(+ 3 5)) 8 ->(setq x’(+ 3 5)) (+ 3 5) ->y Unbound variable:Y ; the number 10 evaluates to itself ; is bound to x and 10 is returned ; the variable x is evaluated to ; return the value it is bound to ; x is reset to the value (+ 3 5) ; and that value returned ; x is reset to the literal value ; (+ 3 5), quote inhibits evaluation ; the variable y was not previously ; bound to a value causing an error
Some basic symbol processing functions are car, cdr, cons and list
Function call (car’(a b c)) (cdr’(a b c))
Value returned a (b c)
Remarks car takes one argument, a list, and returns the first element cdr takes one argument, a list, and returns a list with the first element removed cons takes two arguments, an element and a list and returns a list with the element inserted at the beginning list takes any number of arguments and returns a list with the arguments as elements
(a b c)
Example: ->(cons’(* 2 3)’(1)) ((* 2 3)1) ->(cons(* 2 3)’(1)) (6 1) ; the literal list (* 2 3) is ; consed to the list (1) ; the evaluated list (* 2 3) is ; concerned to the list (1)
makes a list of the top . several lines but parents .->(setq x’(a b c)) (A B C) ->’x X ->x (A B C) • • . extracts the list (b) . x is bound to the literal list . must always balance . elements . the quote inhibits the evaluation . (a b c) . lists may continue on . the list (two three) . arguments are evaluated from left to right and then the function is executed using the evaluated argument values • Example: ->(car(cdr’(a b c d)) B ->(cdr car’((a b)c d)) (B) ->(cons’one’(two three)) (ONE TWO THREE) ->(cons(car’(a b c) (cdr’(a b c))) (A B C) ->(list ’(a b)’c’d)) . extracts the second element ((A B) C D) • Additional list manipulation functions . but unquoted x evaluates to its previously bound value The syntax for a function call is (function-name arg1 arg2…) When a function is called. inserts the element one in .
It simply builds a function which may be called like any other function • Example. returns the last top .5 Defining functions • The function named defun is used to define functions. returns the list with top . returns a single list of . element as a list . It requires three arguments • • The new function name The parameters for the function The function body or lisp code which performs the desired function operations The format is (defun name(parm1 parm2 …) body)… defun does not evaluate its arguments. elements in reverse order .Function call (append’(a)’(b c)) (last’(a b c d)) (member’b’(a b d)) (reverse’(a(b c) d)) Value returned (a b c) (d) (b d) (d(b c) a) Remarks Merges two or more lists into a single list Returns a list containing the last element Returns remainder of second argument list starting with element matching first argument Returns list with top elements in reverse order • Examples: ->(append’(a(b c))’(d e)) (A(B C)D E) ->(append’( a)’(b c)’(d)) (A B C D) ->(last’(a b(c d)(e))) ((E)) ->(member’(d)’(a(d)e f)) ((D)E F) ->(reverse’(a b(c d) e)) (E(C D)B A) . we define a function named average3 to compute the average of three numbes ->(defun average3(n1 n2 n3) . returns the tail of . list from member element . top element input list 3.
predicates return true (t) or false (nil). and nil otherwise . defun returned the name of the function To call the function average3 we give the function name followed by the actual arguments ->(average3 10 20 30) 20 • When a function is called the arguments supplied in the call are evaluated unless they are in quotation marks and bound to the function parameters • The argument values are bound to the parameters in the same order they were given in the definition • The parameters are dummy variables (n1.6 Predicates and Conditionals • • Predicates are function that test their arguments for some specific condition Except for the predicate ”member”.(/(+ n1 n2 n3)3)) AVERAGE3 • . n2. It returns t if the argument is an atom and nil otherwise • Equal takes two arguments and returns t if they evaluate to the same value. depending on the arguments • The most common predicates are atom equal evenp greaterp (or >) <= lessp (or <) • >= listp null numberp oddp zerop The predicate atom takes one argument. n3 in average3 ) used to make it possible to give a general definition 3.
. or zero respectively. . a number.• Evenp. cond returns nil. . otherwise it returns nil • Predicates are to make tests in programs and take different actions based on the outcome of the test • • Cond (for conditional) is like the if. otherwise nil is returned • Lessp requires that the arguments be smaller from left to right to return t. its value is returned and the remaining clauses are skipped over • • • • If <test1> evaluates to nil. If this evaluates to non nil. numberp.else construct The syntax for cond is (cond (<test1> <action1>) (<test1> <action1>) . each returns t. greaterp returns t if the arguments. control passes to the second clause without evaluating <action1> and the procedure is repeated. k is called a clause. i = 1. Each clause consists of a test portion and an action or result portion The first clause following the cond is executed by evaluating <test1>. oddp and zerop are tests on a single numeric argument. They return t if their argument evaluates to an even number. from left to right. . the <action1> portion is evaluated. For example. . . If there is only one argument. If more than one argument is used. If all tests evaluates to nil. to find maximum of two numbers -> (defun max (a b) (cond (( > a b) a) (t b))) MAX . an odd number.. are successively larger. .then. Otherwise they can return nil • Greaterp and lessp each takes one or more arguments.. (<testk> <actionk>)) • • Each (<testi> <actioni>).
• • • When max function is executed. This forces the last clause to be evaluated when the first clause is not -> (max 10 20) 20 • • Logical functions may also be used for flow of control The basic logical operations are and or not • not takes one argument and returns t if the argument evaluates to nil. if all arguments evaluate to non-nil. otherwise it returns nil • For example: -> (setq x ‘(a b c)) (A B C) -> (not (atom x)) T -> (not (listp x)) NIL -> (or (member ‘e x) (member ‘b x)) (B C) -> (or (equal ‘c(car x)) (equal ‘b(car x))) . it starts with the first clause following the cond The test sequence is as follows: if a is greater than b. the value of the last argument is returned. otherwise nil is returned • The arguments of or are evaluated until one evaluates to non-nil. For both. else return b Note the t in the second clause preceding b. it returns nil if its argument evaluates to non-nil • The functions and and or both take any number of arguments. in which case it returns the argument value. the arguments are evaluated from left to right • In the case of and. return a.
This makes it possible to print something and also pass the same thing on to another function as an argument.NIL -> (and (listp x) (equal ‘c (caddr x))) C -> (or (and (atom x) (equal ‘a x)) (and (not (atom x)) (atom (car x)))) T 3. and the sum 11 is returned • Print takes one argument. Output and local variables • • • • The most commonly used I/O functions are read. if found the read statement which caused it to halt and wait for an input from the keyboard. The s-expression is then returned as the value of read and processing continues. its argument is preceded by the carriage-return and line-feed characters and is followed by a space. It prints the argument as it is received. • • When print is used to print an expression. print. terpri and format Read takes no arguments. For example: -> (+ (read)) 6 11 • When the interpreter looked for the second argument for +. princ. and then returns the argument. If we entered 6 as indicated. When read appears in a procedure. prinl. For example: -> (print ‘(a b c)) (A B C) (A B C) . processing halts until a single sexpression is entered from the keyboard.7 Input. read returns this value. processing continues.
it was printed by the read-evaluateprint loop • • The function terpri takes no argument. that is because princ returned its argument and since that was the last thing returned. causing it to be printed by the readevaluate-print loop The print even prints the double quotation marks defining the string Prinl is same as the print except that the new-line characters and space are not provided For example: -> (prinl ‘(hello)) (prinl ‘(hello))) (HELLO)(HELLO) • We can avoid the double quotation marks in the output by using the printing function princ. but the echo still remains. It introduces a new-line wherever it appears and then returns nil For example: to compute the area of a circle -> (defun circle-area () (terpri) (princ “enter the radius”) (setq rad (read)) (princ “The area of the circle is: ”) (princ (* 3. Again.-> (print “hello”) “hello” “hello” • • • • The first print prints its argument and then returns it. It is same as prinl except it does not print the unwanted quotation marks -> (princ “hello”) Hello “HELLO” • Princ eliminated the quotes.1416 rad rad)) .
2656 • • • • • • • • • The princ permits us to print multiple items on the same line and to introduce a new-line sequence we use terpri The format function permits us to create cleaner output than is possible with just the basic printing functions It has the form (format <destination> <string> arg1.(terpri)) CIRCLE-AREA -> (circle-area) Enter the radius 4 The area of the circle is: 50. but intermixed with format directives which specify how each argument is to be represented Directive appear in the string in the same order the arguments are to be printed Each directive is preceded with a tilde characters (~) to identify it as a directive The most common directives are • • ~A The argument is printed as though princ were used ~S The argument is printed as though prinl were used ~D The argument which must be an integer is printed as a decimal number ~F The argument which must be a floating point number is printed as a decimal floating-point number ~C The argument is printed as character output ~% A new-line is printed The field width for appropriate argument values are specified with an integer immediately following the tilde symbol For example: ~5D specifies an integer field of width 5 -> (format t “Circle radius = ~2F~% Circle area = ~3F” x y) . the monitor String is the desired output string. arg2. like to the monitor or some other external file Destination will always be t to signify the default output. …) Destination specifies where the output is to be directed.
consider the variables x and y in the following -> (setq y ‘(a b c)) (A B C) -> (setq x ‘(d e f)) (D E F) -> (defun local-var (x) (setq y (cons x y))) LOCAL-VAR -> (local-var 6) (6 A B C) -> x (D E F) -> y (A B C) • • • • The variable x in the defun is local in scope. It is accessible from any procedure and retains its value unless reset with setq The let and prog constructs permits the creation of local variables The syntax for the let function is (let ((var1 val1) (var2 val2)…) <s-expressions> ) . It reverts back to its previous value after the function local-var is exited The variable y is global.42 » • • • Designate local variables rather than the global assignments which result from setq Parameters named as arguments in a function are accessible only within the function For example.0 Circle area = 9."Circle radius = 3.
The value of the last expression evaluated is then returned • If an initial value is not returned with a vari . it is assigned nil. and any number of s-expressions Prog executes list s-expressions in sequence and returns nil unless it encounters a function call named return. and the parentheses enclosing may be omitted -> (let ((x ‘a) (y ‘b) (z ‘c)) (cons x (cons y (list z)))) (A B C) • The prog function is similar to let in that the first arguments following it are a list of local variables where each element is either a variable name or a list containing a variable name and its initial value • • • • • This is followed by the body of the prog. each vali is evaluated and assigned to the corresponding vari. In this case a single argument of return is evaluated and returned Prog also permits the use of unconditional go statements and labels to identify the go-to transfer locations With the go and label statements.• • Where each vari is a different variable name and vali is an initial value assigned to each vari respectively When the let is executed. an element and a list -> (defun memb (el 1st) (prog () Start (cond (( equal el (car 1st)) (return 1))) (setq 1st (cdr 1st)) (go start))) . prog permits the writing of unstructured programs For example. and the s-expressions which follow are then evaluated in order. the main function memb requires two arguments.
8 Iteration and recursion • The structured form of iteration with the do construct is (do (<var1 val1> <var-update1>) (<var2 val2> <var-update2>) . The second clause of the cond executes when the first clause is skipped because setq is non-nil 3. they are executed each iteration until an exit test condition is encountered For example. the factorial function -> (defun fact(n) (do ((count n(. (<test> <return-value>) (<s-expression>)) • • • • The vali are initial values which are all evaluated and then bound to the corresponding variables vari in parallel After the variables are updated during an iteration. The label start. the return value is evaluated and returned The s-expressions forming the body of the construct are optional. the transfer point for the go statement.MEMB • The prog here requires no local variables. If present. and if it returns true. the test is evaluated.count 1)) (product n (* product (. .count 1)) ((equal 0 count) product))) FACT • In this definition there is no need to include a body .
weight. address Property list functions permit one to assign such properties to an atom. say an atom which represents a person. and to retrieve. replace or remove them as required. the factorial of a number -> (defun fact(n) (cond (( zerop n) 1) (t (* n (fact (-n 1)))))) FACT -> (fact 6) 720 3. except the assignment of initial values is made to each vari sequentially before the next form is evaluated Loop has the simple form (loop <s-expressions>) • • • • • Where the s-expressions are evaluated repeatedly until a call to a return is encountered let and other functions can be embedded within the loop construct if local variables are needed A recursive function is one which calls itself successively to reduce a problem to a sequence of similar steps Recursion requires a stopping condition and a recursive step For example. can be given a number of properties such as height.9 Property lists and arrays • • • The most useful unique features of LISP as an AI language is the ability to assign properties to atoms Foe example: an object.• • There is also a do* construct which is the same as do. .
It takes three arguments: an object name. use the function get The function get takes two arguments object and attribute -> (get ‘car ‘color) RED -> (get ‘car ‘make) FORD -> (putprop ‘car ‘green ‘color) GREEN -> (get ‘car ‘color) GREEN • • The property value may be an atom or list Some versions of common LISP do not provide the putprop function. such as color of car. a property or attribute name. and a property or attribute value For example to assign properties to a car -> (putprop ‘car ‘ford ‘make) FORD -> (putprop ‘car 2009 ‘year) 2009 -> (putprop ‘car ‘red ‘color) RED • • • • • The form of putprop is (putprop object value attribute) where value is returned The remprop function takes two arguments.• • The function putprop assigns properties to an atom. the object and its attributes Properties are global assignments To retrieve a property value. so define our own -> (defun putprop (object value property) .
the first may be either an atom or an access function (like car. the name of the array and the index value. to create an array with ten cells named myarray. The cells are indexed starting at zero -> (aref myarray 9) NIL • • To store the items in the array.(setf (get object property) value)) PUTPROP • • Setf function is like setq function Setf is an assignment function . we bind the unquoted name to an array using sef or setq with the make-array function and a specification of the number of cells -> (setf myarray (make-array ‘(10))) # A(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) • • The function returns the pound sign followed by an A and the array representation with its cells initially set to nil To access the contents of cells. use the function aref which takes two arguments. use the function setf For example: to store the items 25 and red in the first and second cells of myarray -> (setf (aref myarray 0) 25) 25 -> (setf (serf myarray 1) ‘red) . which takes two arguments. cdr and get) and the second arguments are the value to be assigned • For example: -> (setf (get ‘car ‘color) ‘pink) PINK -> (get ‘car ‘color) PINK • • Single and multiple-dimension arrays may be defined in LISP using the make-array function Foe example.
' prompt. They are widely regarded as excellent languages for "exploratory" and "prototype programming". SWI Prolog has extensive help information. A startup message or banner may appear. adopted Prolog as a development language. To learn more about it. The name itself. This help is indexed and guides the user. • Prolog is the major example of a fourth generation programming language supporting the declarative programming paradigm. open a terminal window and type the approprite command. followed by a carriage return. For example.RED 3. The first detailed description of the Prolog language was the manual for the Marseille Prolog interpreter (Roussel. • Lisp and Prolog are the most frequently used symbolic programming languages for artificial intelligence. announced in 1981. • Prolog's heritage includes the research on theorem provers and other automated deduction systems developed in the 1960s and 1970s. • The other major influence on the nature of this first Prolog was that it was designed to facilitate natural language processing. SWI-Prolog installs a start icon that can be double-clicked to initiate the interpreter.10 PROLOG and other AI programming languages • Prolog is a logical and a declarative programming language. Notice that all of the displayed symbols need to be typed in. • How to Run Prolog To start an interactive SWI-Prolog session under Unix. and thereby focused considerable attention on the language and its capabilities. and that will soon be followed by a goal prompt looking similar to the following ?. 1975)._ Interactive goals in Prolog are entered by the user following the '?. on our Mac this is . try? help (help)... The interpreter then starts in its own command window. Many Prologs have command-line help information. Prolog. /opt/local/bin/swipl $ Under Windows. is short for PROgramming in LOGic. • The "first" Prolog was "Marseille Prolog" based on work by Colmerauer (1970). • The Japanese Fifth-Generation Computer Project. .
Load a program from a local file*/ factorial(0.. Load another program */ takeout(A. or to select text in a Prolog Tutorial web page. yes ?.listing(takeout). */ next to goals are referred to in the notes following the session. Compute factorial of 10 */ ?.listing(factorial/2). or obtained by saving a text file while using a web browser.[B|C]. consider the following sample session. takeout(A. B is A*D. which was created by the user. ?.factorial(10. /* 4. yes . yes ?.D). List program to the screen*/ /* 1.[B|D]) :takeout(A.[A|B]. The way to achieve the latter is either to follow a URL to the source file and then save. paste into a text editor window and then save to file.B) :A > 0.['2_7. To illustrate some particular interactions with prolog.['2_2. Each file referred to is assumed to be a local file in the user's account. factorial(A. C is A-1. The comments /* .D). /* 2.pl']. What=3628800 /* 3. copy it.What).pl'].B).. ?.1).C. factorial(C. obtained by copying directly from some other public source.
X>3. X=2 Y=[1. 'X>3'. and so on. Prolog satisfies the goal by finding the value of the variable 'What'.4]. 'factorial(10.halt. Compiled predicates do not have an interactive source listing that can be supplied by a 'listing' goal. then Prolog stops looking for answers.?..4].in this case. how Prolog is prodded to produce all of the possible answers: After producing each answer. as shown in the response. Several files can be chain loaded by listing the filenames sequentially within the brackets. The goal here.4] . In the program just loaded is a definition of the logical predicate 'takeout'. Note the arithmetic goal (built-in relation)..3. Means: No more answers.3. There are four ways to do this.takeout(X. from the two source files 2_2.3.4].. Both "programs" now reside in memory. in all possible ways.2.4] leaving remainder list Y. If the user types a semicolon '..2. ?. the predicates were declared as dynamic in the source code before this sample run. no Prolog waits .[1._). However.What)'. The built-in predicate 'listing' will list the program in memory -.4] */ X=1 Y=[2. separated by commas.pl and 2_7. denoting a logical variable....' and Enter again .[1. The word 'What' begins with an upper-case letter. X=3 Y=[1. Conjunction of goals */ X=4 .4] .2. essentially says "the factorial of 10 is What?". again .Y)' asks that X be taken out of list [1. /* 6. Prolog will attempt to satisfy these goals in . again .pl.3. Return to OS */ A Prolog goal is terminated with a period ". Prolog will look for a next answer." In this case the goal was to load a program file.4] .2. The goal 'takeout(X. User types '. in order to illustrate this Prolog interpreter feature. no ?.takeout(X.3.2. If the user just hits Enter. This "bracket" style notation dates back to the first Prolog implementations.2. So. Take X out of list [1. the factorial program.Y).3. X=4 Y=[1. /* 5.[1. A compound or conjunctive goal asks that two individual goals be satisfied.3. Prolog waits with a cursor at the end of the answer. /* 7.2..' .3] .
The head of a clause is the whole clause if the clause is a unit clause. Note the use of an anonymous variable '_' in the goal.W)'. The first of these definitions is: factorial(0.W). The body of the second clause is on the right side of the ':-' which can be read as "if". but instead has instances (values) of . W=6 Consider the following clause tree constructed for the literal 'factorial(3. because it does have a body.' each of which can be read as "and".1). A declarative reading of the first (unit) clause says that "the factorial of 0 is 1" and the second clause declares that "the factorial of N is F if N>0 and N1 is N-1 and the factorial of N1 is F1 and F is N*F1".factorial(3.F) :N>0.F1). the goal variable: ?. The second is a rule. Two factorial definitions To compute the mathematical functions using Prolog. • The 'halt' goal always succeeds and returns the user to the operating system. This program consists of two clauses. The clause tree does not contain any free variables. factorial(N1. Two predicate definitions that calculate the factorial function are in file 2_2.the left-to-right order.pl. The Prolog goal to calculate the factorial of the number 3 responds with a value for W. N1 is N-1. there is only one answer. The first clause is a unit clause. F is N * F1. otherwise the head of a clause is the part appearing to the left of the colon in ':-'. The body consists of literals separated by commas '. factorial(N. having no body. which the reader can view by clicking on the 'Code' link at the bottom of this page. for which no binding is reported ("don't-care variable"). just as they would be read. In this case.
factorial(3.2)' is that it is false. That is. 3. we have not drawn 'true' leaves under the true arithmetic literals.1): . in fact.true is a Prolog goal that always succeeds (true is built-in).6)' all of whose leaves are true. For the sake of brevity.1 All of the arithmetic leaves are true by evaluation (under the intended interpretation).6).2).2)' is. Thus the meaning of the program for the literal 'factorial(5.factorial(5. not a consequence of the program because there is no clause tree rooted at 'factorial(5.variables. Fig. using relevant instances of the variables. The program clause tree provides a meaning of the program for the goal at the root of the tree. 'factorial(3. the node is determined by some instance of the head of a clause and the body literals of the clause determine the children of the node in the clause tree. on the other hand.6)' is a consequence of the Prolog program. yes ?. no .2)' having all true leaves. ?. Each branching under a node is determined by a clause in the original program. ?. and the lowest link in the tree corresponds to the very first clause of the program for factorial. That first clause could be written factorial (0. The literal 'factorial(5.true. and. because there is a clause tree rooted at 'factorial(3.
% The debugger is switched off . in order for the root to be a consequence of the program. approach to program semantics.X)._8140) ? (2) 1 Call (built-in): 3>0 ? (2) 1 Done (built-in): 3>0 ? (3) 1 Call (built-in): _8256 is 3-1 ? (3) 1 Done (built-in): 2 is 3-1 ? (4) 1 Call: factorial(2. Clause trees are so-called AND-trees. Clause trees do provide an intuitive. The clause trees are "static" and can be drawn for a program and goal regardless of the particular procedural goal-satisfaction mechanism.. (1) 0 Exit: factorial(3.6) ? X=6 [trace] ?. take into account the variable-binding mechanism of Prolog and the order that subgoals are considered. The following sample shows how a typical Prolog tracer is turned on and off. % The debugger will first creep -._8140) ? (1) 1 Head : factorial(3. ?. We have indicated that clause trees provide a meaning or semantics for programs. To distinguish between the program clause trees and so-called Prolog derivation trees. Derivation trees.factorial(3. The clause trees correspond to the declarative reading of the program. each of its subtrees must also be rooted at literals which are themselves consequences of the program. _8270) ? . since.showing everything (trace). as well as a correct.notrace. (1) 0 Call: factorial(3. A trace of a Prolog execution also shows how variables are bound in order to satisfy goals..trace. yes [trace] ?. on the other hand.
factorial(5.X).yes Here is the other one. with the same predicate name.] as a list builder. factorial(N. car([X|Y]. N1 is N -1.2. factorial(0. . For this version. cons(X.. The notation [X|Y] refers to a list whose first element is X and whose tail is Y. cdr([X|Y].. and 'cons' is the list constructor. This version is properly tail recursive. A1 is N*A. The following three definitions should make sense to a Lisp programmer. such as [1. use the following type of a goal: ?.3. where 'car' refers to the first element of a list. A finite list can be explicitly enumerated.F). 'cdr' refers to the tail or rest of the list. but using three variables.R.F).[X|R]).1.F.4].F) :N > 0.Y). Prolog Lists Prolog uses brackets [.A. F=120 The second parameter in the definition is a so called an accumulating parameter.A1. factorial(N1.F).
member(X.R). Putting X at the head and Y as the tail constructs (cons) the list [X|R].[X|R]).2.. Consider the following definition of the predicate 'member/2'. . X is a member of a list whose tail is R if X is a member of R. However. member(X. One can read the clauses the following way. X=1.[1. The tail (cdr) of [X|Y] is Y.. No Here is a derivation tree showing how this last goal generated all of the answers. Yes One can generate members of a list: ?. if the list can be unified with the Prolog term '[X|Y]' then the first element of the list is bound to (unified with) X and the tail of the list is bound to Y. Conversely.member(X.member(2.member(X.3]). This program can be used in numerous ways. The head (car) of [X|Y] is X. A list whose head is X and whose tail is Y can just be referred to using the Prolog term [X|Y].meaning . One can test membership: ?.[1.[Y|R]) :. respectively: X is a member of a list whose first element is X. X=2.3]).2. we will see that these explicit definitions are unneeded. X=3.
6]).a]. 3.9.Fig.p]])..45.v]. Y=z.member(X. Y is X*X.m]. No The definition for 'member' is usually written .[3. Here is another..222. No . Y=p.2 Each left branch corresponds to a match (unification) against the first clause for 'member' and each right branch corresponds to a match against the second clause.67.)' on the lowest right branch will not match the head of any 'member' clause. We will find many other uses for 'member'. The subgoal 'member(X.. [[1. ?. suggests a use where one intends to search in order to find elements paired with a specified element.[2. finding elements of a list which satisfy some constraint: ?.[23.[3. Y < 100.Y]..12. In particular '' will not unify with a pattern of the form '[X|R]' because the latter represents a list with at least one element.z].19. X = 9 Y = 81 .member([3.[4. This example query . X = 6 Y = 36 .
R).R. they match any Prolog term.takeout(X. [1. When X is taken out of the tail of [X|R].3].[F|S]) :. No Notice that it would not be appropriate to use any anonymous variables in the definition of 'takeout'. For example.3].[2. X=3 L=[1. but no variable binding results from the free match.3]. In general. takeout(X.2. takeout(3.3] . X=2 L=[1.member(X. Notice that this is consistent with the original intentions of the definition of 'member'.[1.S).[_|R]) :. X=1 L=[2.2] . Related to 'member' is the following definition for 'takeout'.[1.2.[1.R). Not having to bind values to anonymous variables saves a little run-space and run-time. where S is the result of taking X out of R.member(X.[1. In effect.takeout(X.2.) | . such variables have names whose first character is the underscore.[X|_]). takeout(X.L).[X|R]. member(X. [X|S] results. Pay particular attention to exactly how the clauses are used to construct the tree. where '_' (underscore) designates a "don't-care" variable.2])' is a consequence of the definition. usually called anonymous variables.2]) | | takeout(3.[F|R]. These clauses can be paraphrased in English as follows: • • When X is taken out of [X|R]. Here is a program clause tree showing that 'takeout(3. R results. ?.3].3] .
one could define putin(X.R.c] .5]).2.[4.[a.R) :.4.[1. 'takeout' got its name from just one of its uses. Several kinds of goals are possible: ?.W.2.. That is.3].W)' can also be interpreted as "insert X into W to produce Z".| takeout(3.2. append(.5]).append(Y. Of course.A)..3.4.Z..5] .[X|W]) :. W = [a.X.3].b.3] .takeout(3. W = [4.append([1. ?.c] .3. W = [a.3]. two Prolog lists.W.c. or concatenating.takeout(X.b.append([1.a.c]).3.L. W = [3.4.3.c] . No shows that 'takeout(X.Z.Z. Reversing a list can be done with . Here is a definition for appending.X).L).b.W). W = [a.b.5].2. and so on.) | | true The following goal. append([X|Y].2. Yes ?.append([1.[4.3.5] ?.5]. A = [1.b.[1.2.
Z. reverse(A. consider the following (partial) derivation tree ?.A) | | reverse(.). For example..reverse([X|Y]. Here is an interesting definition designed to produce all possible permutations of a list.X).A) | | reverse(.reverse([1. and then the second 'reverse' clause is used to "capture" the answer by matching the second and third arguments.X.. perm([X|Y].Z) :.2. takeout(X. One could use the following definition to "hide" the accumulating parameter.A) | | reverse([2.W) :.perm(Y.2.3].reverse(A.2. This program illustrates Prolog's approach to an important strategy -.[3.R).W).Z.R) :. Think of 'takeout(X. reverse(.Z.to accumulate a list answer until the computation is finished. Then the definitions could paraphrased as follows: .3].1].1].W).using an accumulating parameter (the middle variable) -.W).reverse(Y.A) | | true A = [3..1] where the first 'reverse' clause is use three times.[2.W)' as being used in the "X put into W yields Z" sense here. perm(.[X|Z].
member(X. and a list can have multiple occurrences of a particular element (sets do not).subset([4.• • Z is a permutation of [X|Y] provided W is a permutation of Y and then X is put into W to produce Z . No The user should try the goal '?.S) :.5.' It is common to represent sets as Prolog lists.perm(P. P = [1.3].4]).[2.1] . subset(R.2.1. Yes work fine.P). P = [3. However.  is the (only) permutation of .3.3] .1] . Subsets can be tested using subset([X|R].1.2] . P = [2.3]. P = [3.3]). P = [2. Here is a sample goal for 'perm': ?.2. . P = [1.3])' not be reasonable goals? Union and intersection can be approximated using the following Prolog list versions: union([X|Y].2. Why would '?. union(Y.2.member(X. Set membership can be computed using the 'member' relation for lists previously discussed.Z. the list representation is very convenient.[1. subset(.Z). such as the fact that Prolog lists are inherently ordered (sets are not).W).S)._).2]. This representation has some flaws.[1.W) :.subset([1.subset(A.3.Z.perm([1.3] .3. Goals like ?.W)' and '?.2] .2.S).
a.4].2.a. intersection(.Z.\+ member(X.M.Z).B).Z).union([X|Y]. /* do not use next clauses */ union(Y. union(Y.[1.B)' which is intended to remove multiple occurrences of elements from A to produce result B.[X|Z]) :.M).Z.).b].[1. B = [1.b.4] Why would goals like '?. ?.[X|W]) :. .B).4].prune([a.1.Z.4] Try to make it so that B has remaining elements in the order that they occurred in A.Z) :. These are intended to be used for goals where the first two variables already have a list value. intersection(Y.A).1.3. B = [a.W).Z. For example.Z.a.b.Z).-)' to indicate the intended variable profile.3.member(X.Z.union([1. union([X|Y]. union(.[2.Z).W) :member(X. Ex: Design and test 'prune(A.M. intersection([X|Y].W).4.b.3].M.3.2.+.a.Z). ?.W).1.2.union(Y.3.2.a.union(X.4].2])' cause difficulty? Some run-time inefficiency results from having to rematch the heads of clauses for both of the definitions.3.Z.a. Sometimes this intention is indicated by writing something like 'union(+.4] ?. For example.3.4].b.Z.[1.M. intersection([X|Y].[X|W]) :.b.Z).M). using ! instead: union([X|Y].intersection([1. !. union(.\+ member(X. A = [2. intersection(Y. Here is an alternate version of union.M.
segment([a.a.L1. W =  .L2). W =  . mergesort(L2. Yes ?.segment([a. W = [1.[1.[1.c].3.B|R].S2.).c. No ?. ?.B|R].2].a. For example.[c.-).c.prefix(W.2. yes ?.b]. mergesort(. with intended profile mergesort(+. No Ex: Design a Prolog predicate 'segment'. For example.a.prefix([1.b]).3]). No Various sorting strategies can be implemented using lists in prolog. that tests whether its first list argument is a contiguous segment contained anywhere within the second list argument. ?.c.3]. .[A]).3]). Here is a Prolog version of merge sort. /* covers special case */ mergesort([A].b.[1. W = [1.prefix([1. and which can generate prefixes of a given list.b. mergesort(L1.Ex: Design and test 'prefix(A.3]).2.S1). mergesort([A.S).3] .[1.2] .S2).S) :split([A.5]).B)' which tests to see if A is a list prefix of B.22.214.171.124. merge(S1.
Longer sequences have elements separated by commas ".op(1000.'. split([A].9. meaning that comma is right-associative with precedence 1000.(a) = a. merge(Ra. merge(..[B|Rb]. H=1 T = 2.split(R.1. S=[1. split([A.Ra.[B|Rb]) :.3.6. but often have very cogent specifications in Prolog. An appropriate declaration for the comma operator would be :. merge([A|Ra].4 ?.split(.) Here is some Prolog behavior.).3.B|R].T) = (1.A =< B.A).[A|M]) :.M). No . ?. The shortest sequence has one element. merge(A.[B|Rb].3. merge([A|Ra].2.Rb. Here is a sample goal: ?.3. Yes ?.7]. Prolog Sequences The kind of sequences most used in Prolog are "comma" sequences.(H.[B|Rb].xfy. There is no empty sequence (unlike for lists).5.4).A > B.).Rb).7.[B|M]) :.5.[A].T) = (a).9] Prolog list sorting routines suffer all of the relative space and time inefficiencies related with sorting dynamic structures.. merge([A|Ra].S).mergesort([4. (The comma operator is actually built-in.".6.B.B).4.[A|Ra].(H.').M).
clause(a(X).yfx.S. For example. c..C) = (1. 2.b(X). 3. sequence_append((X. whereas for lists the base case is for the empty list.assert((a(X) :.B. d(G1176) Body = b(G1176).b.3).. to make leftassociative sequences separated by '#'. ?.Next).5).(A#B) = 1#2#3#4. For example. First = b(G1176) Next = c(G1176).sequence_append((1. b. except that the base case for sequences is a unit sequence (one element). sequence_append((X).(X.S).5 Prolog clauses use comma sequences. ?.?.d(X))).S. Yes ?. a.4. Note the use of cut (!) to make sure that the second clause is not available as a alternate choice for multi-element sequences..T)) :!.d)..'#'). Body=(First.op(500. A=1 B=2 C = 3.R). here is a program to append comma sequences . ?. one might use an operator declaration like this .(X. c(G1176).c(X).2. sequence_append(R.3.c.S.T).4.Body).2. B=4 A=1#2#3 .(A. S = 1.S)). %% Note parens around clause X = G1056 ?. d Other kinds of sequences can be defined by the user.(a. d(G1176) X = G1176 Procesing sequences is similar to processing lists.
Note the full-stop at the end. e. To exit the Prolog system type: halt. will have to enclose it within quotes: consult arguments. for instance: consult(‘~/prologprogs/ex1. expressing the functional relation square(5)?25. and instead concentrate on providing a precise notation in which computation is a form of reasoning. This contrasted with functional languages where a call may be regarded as a mathematical function. a call square(5) is considered as rewriting to 25. which loads a program from a file. and a database language. A call to any procedure in the program may be made by typing the call in response to the prompt. To return to the idea of relations. and the procedures in the file name will be loaded. Among the built-in procedures is consult. in response to the prompt. Help on any Prolog built-in procedure can be obtained by calling the built-in procedure help.pro’). A number of procedures are built-in. Prolog is a relational language. a Prolog call may can be be regarded as characters. which takes an integer and squares it.g: help (consult). Both functional and relational languages however are considered declarative. in a functional language we might have the function square. that is they break away from the idea of a programming language as a set of instructions to manipulate the memory of a computer (such languages are referred to as imperative). The file will be taken from your top level directory. that is they exist before any other program is loaded. but you may use a full path to access files in other directories. Prolog originates from attempts to provide a computer-executable form of mathematical logic notation (its name comes from Programming in Logic).Notice how left-associativity was what determined the bindings in the second goal! • Prolog may be considered as a relational language. The current program consists of whatever procedures have been loaded. thus it and similar languages are often referred to as the logic languages. That expressing a relation between its is. If the filename starts with a capital letter. a non-deterministic language. Type: consult (<filename>). The equivalent in . or contains non-alphanumeric ('<filename>'). • Prolog as a Relational Language Prolog is an interpreted language.
as that has a different effect. A program for square consists of just the single line: square(X. Considering declarative languages in terms of the imperative language like C. square(Y. a procedure to give the difference of two squares may be given by: diff2squares(X. … X k ) :. A logic language may be considered as programming in procedures which do not return values directly (void in C terminology) and in which variable parameters are always passed by reference (preceded by & in C terminology) though the variables can only be assigned new values within the procedure if they were unassigned when the procedure was called.call 1 . call n is then executed in turn.X). while a procedure name may be any alphanumeric string starting with a small letter. Each of call 1 . . … X k are Prolog variables. and call 1 . call n Prolog procedure calls. ….square(X. Here X is a Prolog variable. where X 1 . D is X2-Y2. …. If a correct program for square has been loaded.X2).X) to be true. …. The call is (expressible in infix form) is used to give arithmetic calculation. The underscore character '_' is treated as an additional capital letter in names.Y) :. …. Don’t mistakenly use = in its place.e. As an example. When a call proc(arg 1 .D) :. call n may contain variables from X 1 .X). if we have the existing procedure square. This says that X and Y are in the relationship square if Y is X*X evaluated arithmetically. will cause X = 25 to be printed. one which takes k arguments). or new variables. … X k among its arguments. A Prolog procedure for a k-ary relation (i. … arg k ) is made. indicating that X must have the value 25 for the relation square(5. You need to type a carriage return after this to get the prompt for the next call.Prolog is a call square(5. Each of call 1 .Y.Y2).Y is X*X. Note that a variable name may be any alphanumeric string starting with a Capital letter. a functional language may be considered as programming in terms of functions which return values but do not have any side-effects. named proc takes the form: proc(X 1 . typing square(5. or constants. any occurrence of a variable X i among the calls is replaced by arg i . call n .
We discussed recursion. We saw how to define and use local variables with the let and prog functions. We saw how to write iterative programs with the do. square(Y. We also defined a number of predicate functions such as equal. append. and the list manipulation functions (car. We then described how to define our own functions using defun. One very important point to note is that Prolog variables may only be assigned a value once in a procedure body.B). the result is that execution of the is call will cause the variable to store the result of evaluating the formula. or. Array definitions and examples were briefly introduced. terpri. loop.12 Keywords • • • LISP Prolog Atom . member. and prog constructs. -. We concluded the chapter with a few comments regarding other AI languages. and format were defined and example programs presented. a valuable method with which to assign multiple values or properties to variable atoms. 3. and so on. the lambda form. And a few miscellaneous topics such as mapping functions (mapcar). A is A-B. *. If the left-hand side of is is a variable. and reverse). the programming language of AI. and gave some simple examples of its use. listp. null. since here. we introduced the logic programming language PROLOG. and the right-hand side an arithmetic formula. numberp. We saw how to use the conditional cond and the logical functions and. We then looked at property lists. Finally.A).square(X. list. 3. We defined LISP syntax and examined a number of built-in functions. once A has been assigned a value in the call square(X. princ. /).11 Summary In this chapter we introduced LISP. The input-output functions print. and not. and internal list representations concluded our treatment of LISP.Y. cdr. atom. cons.A) :. that value cannot be changed by the further call A is A-B. prinl. last. and saw examples of its use.A). You could not have: diff2squares(X. read. including the numeric functions (+.
4. If the item is in the list. Define a function called rotate that takes a list and rotates the element by one position as in (rotate ‘(a b c d)) return (D A B C). new list returns it without change. Define a function named add list that takes two arguments an item and a list.13 Exercise 1. Define a function called number of elements that takes a list as its only argument and returns the number of top elements in the list.• • • • • • • • • • • • • • • • • List String Setq Cons Car Cdr Append Member reverse Last Defunct Equal Evenp Numberp Greatyerp Lessp cond 3. 6. If the argument is already a list. including the empty list. If the item is not in the list the function returns the list with the item entered as the first element. Write a LISP program to convert centigrade temperatures to fahrenheit. For example: (add list ‘c ‘(a b c d)) returns (a b c d) but (add list ‘e ‘(a b c)) returns (e a b c) . If the argument is an atom it returns it as a list. 5. Define a function new list that takes one argument and returns it as a list. Define a function called first element that takes a list as its argument and returns the first top element of the list. 3. the function returns the list unaltered. 2.
Write an iterative function named nth item that takes two arguments. If the word typed is a member of the list. The function computes the nth power of m(mn). Write a recursive function named power that takes two numeric arguments n and m. . Be sure to account for the case where n = 0. The function should print a prompt to the user (please type any word). The function returns the item in the nth position in the list. 8. which takes two lists as arguments. a positive integer and a list. which takes one list as argument. Write a function called word member.7. The function should return a list containing single occurrences of all elements which appear in both input list. Write a function called intersection. 10. 9. If the integer exceeds the number of elements in the list. it returns nil. the function should return t otherwise nil.
This action might not be possible to undo. Are you sure you want to continue?