Home Previous Next

CSC240 :: Lecture Note :: Week 11
Assignments | Code | Handouts | Resources | Email Thurman {Twitter::@compufoo Facebook::CSzero}
{GDT::Bits:: Time  |  Weather  |  Populations  |  Special Dates}

Overview

Assignment(s): [all assignments have been assigned]

Code: cons.cpp | dot-listp directory listing


Introduction to Lisp

Lisp (LISt Processing) was created by John McCarthy. Via Wikipedia.org: "John McCarthy (September 4, 1927 - October 24, 2011) was an American computer scientist and cognitive scientist. McCarthy was one of the founders of the discipline of artificial intelligence. He coined the term "artificial intelligence" (AI), developed the Lisp programming language family [...]." John McCarthy was awarded the ACM Turing Award in 1971.

Note: Lisp does not stand for "Lots of Irritating Superfluous Parentheses."

The clisp command executes the "Common Lisp" interpreter and compiler.

clisp runs in interactive mode (read-eval-print loop) when executed with no arguments. Nutshell: READ an expression from the standard input; EVALuate the expression; PRINT results to standard output.

The format of clisp prompts: [n]> (where n is the command number).

$ clisp
  i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo
  I I I I I I I      8     8   8           8     8     o  8    8
  I  \ `+' /  I      8         8           8     8        8    8
   \  `-+-'  /       8         8           8      ooooo   8oooo
    `-__|__-'        8         8           8           8  8
        |            8     o   8           8     o     8  8
  ------+------       ooooo    8oooooo  ooo8ooo   ooooo   8

Welcome to GNU CLISP 2.49 (2010-07-07) 

Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010

Type :h and hit Enter for context help.

[1]> (bye)
Bye.

Many commands like clisp support a "quiet mode" that is turned on by executing them using either a -q or --quiet option. {clisp.org::man clisp (manual page)}

$ clisp --quiet
[1]> (bye)

Let's start again using "quiet mode."

$ clisp -q

[1]> "hello, world"
"hello, world"

[2]> "0 or more characters in double quotes is a string"
"0 or more characters in double quotes is a string"

[3]> "comments start with a ; and end at end-of-line" ; this is a comment
"comments start with a ; and end at end-of-line"

[4]> "three types of numbers: integer, floating-point, ratio"
"three types of numbers: integer, floating-point, ratio"

[5]> 240  ; is-an integer
240

[6]> -240 ; is-an integer
-240

[7]> 3.14 ; is-a floating-point
3.14

[8]> "number and strings evaluate to themselves"
"number and strings evaluate to themselves"

[9]> "lisp supports ratios when integer arguments are used"
"lisp supports ratios when integer arguments are used"

[10]> 5/7
5/7

[11]> "you can use ratios to reduce fractions"
"you can use ratios to reduce fractions"

[12]> 42/240  ; proper fraction
7/40

[13]> 240/7  ; improper fraction
240/7

[14]> 240/8  ; prints an integer if denominator is 1
30

[15]> 240/100
12/5

[16]> 240/100.0  ; ratio arguments must be integers
*** - SYSTEM::READ-EVAL-PRINT: variable |240/100.0| has no value

[17]> 6.62607004e-34   ; floating-point in scientific notation
6.62607E-34

[18]> "let's look at symbols"
"let's look at symbols"

[19]> T       ; true (any value that's not nil)
T

[20]> t       ; not case sensitive (case insensitive?)
T

[21]> nil     ; false (or empty list)
NIL

[22]> Nil     ; not case sensitive
NIL

[23]> NIL
NIL

[24]> (exit)  ; same as (bye) and (quit)
Numbers in Other Number Systems
[1]> #b1010    ; base-2 (binary)
10

[2]> #o31      ; base-8 (octal)
25

[3]> #x2b      ; base-16 (hexadecimal)
43

[4]> #12r180   ; base-12 (can go up to 36)
240

[5]> #36r6o   ; base-36
240

[6]> #60r240  ; base-60
***error: The base 60 given between # and R should lie between 2 and 36

{TopOfPage} {Resources}


Number Operations

Lisp is a "prefix notation" language.

Arithmetic operators are functions having the following syntax.

   (function_name arguments) 

The arithmetic functions are named + - * / for addition, subtraction, multiply, and divide, respectively.

Quoting Peter Seibel: "Lisp was originally designed by a mathematician as a tool for studying mathematical functions."

Addition and Subtraction
$ clisp -q

[1]> (+ )
0

[2]> (+ 2)
2

[3]> (+ 2 3)
5

[4]> (+ 2 3 4)
9

[5]> (- )
*** - EVAL: too few arguments given to -: (-)

[7]> (- 4)
-4

[8]> (- 4 2)
2

[9]> (- 2 4)
-2

[10]> (- 4 2 1)
1

[11]> (- -3 -2)
-1

[12]> (- pi)
-3.1415926535897932385L0
Multiplication
$ clisp -q

[1]> (* )
1

[2]> (* 5)
5

[3]> (* 4 2)
8

[4]> (* 4 2 3)
24

[5]> (* 4 -5)
-20
Division
$ clisp -q

[1]> (/ )
*** - EVAL: too few arguments given to /: (/)

[3]> (/ 5)
1/5

[4]> (/ 5 2)
5/2

[5]> (/ 5 2.0)
2.5

[6]> (/ 6 2)
3

[7]> (/ 3 6)
1/2

[8]> (/ 12 2 2)
3

[9]> (/ 4 -2)
-2

[10]> (/ 4 0)
*** - /: division by zero
Predicates
$ clisp -q

[3]> (oddp 5)            ; predicate function names usually end in p
T

[4]> (oddp 10)
NIL

[5]> (evenp 5)
NIL

[6]> (evenp 10)
T

[13]> (zerop 10)
NIL

[14]> (zerop 0)
T

[15]> (plusp 12)            
T

[16]> (plusp -12)
NIL

[17]> (typep 240 'integer)    ; ' is the quote character
T

[18]> (typep 240 'float)      ; or do (typep 240 (quote float))
NIL

[19]> (typep 240 'long)
*** - TYPEP: invalid type specification LONG

[20]> (typep 240 'string)     ; or do (typep 240 (quote string))
NIL

[21]> (typep 240 'double)
*** - TYPEP: invalid type specification DOUBLE

[22]> (typep 240 'real)
T

[23]> (typep 240 'number)
T

[24]> (typep 240 'character)
NIL

[25]> (typep 240 'complex)
NIL

[26]> (integerp 240)
T

[27]> (floatp 240)
NIL

[28]> (complexp 240)
NIL

[29]> (stringp 240)
NIL

[30]> (characterp 240)
NIL

[31]> (numberp 240)
T

[32]> (typep "240" (quote string))
T

[33]> (typep "240" 'string)
T

[34]> (stringp "240")
T
Increment/Decrement
$ clisp -q

[1]> (1+ 0)
1

[2]> (1+ 1)
2

[3]> (1+ 2)
3

[4]> (1- 3)
2

[5]> (1- 2)
1

[6]> (1- 1)
0

[7]> (1- 0)
-1

[8]> (1+ 3.1416)            ; strange evaluation
4.1415997

[9]> (1- 3.1416)
2.1416
Math Functions
$ clisp -q

[1]> (gcd 20 30 40 50)   ; greatest common divisor
10

[2]> (lcm 1 2 3 4)       ; least common multiple
12

[3]> (rem 5 2)           ; the % operator in C and Java
1

[4]> (abs -5)            ; absolute value
5

[5]> (max 5 92 1 3 1 6)
92

[7]> (min 5 92 1 3 1 6)
1

[18]> (random 10)
9

[19]> (random 92.31)
27.658089

[20]> (floor pi)
3 ;
0.14159265358979323851L0

[21]> (ceiling pi)
4 ;
-0.8584073464102067615L0

[22]> (round pi)
3 ;
0.14159265358979323851L0

[23]> (truncate pi)
3 ;
0.14159265358979323851L0

[24]> (mod 240 7)
2

[25]> (ext:! 4)    ; ext: indicates an extension
24
Exponents/Logarithms
$ clisp -q

[1]> (expt 2 5)
32

[2]> (expt 5)
*** - EVAL: too few arguments given to EXPT: (EXPT 5)

[4]> (exp 5)
148.41316

[5]> (expt 0)
*** - EVAL: too few arguments given to EXPT: (EXPT 0)

[6]> (expt 5 0)
1

[7]> (sqrt 5)
2.236068

[8]> (sqrt 25)
5

[9]> (log 100)           ; base-e (natural logarithm)
4.6051702

[10]> (sqrt -1)          ; complex numbers supported
#C(0 1)

[11]> (isqrt 5)          
2

[12]> (log e)
*** - SYSTEM::READ-EVAL-PRINT: variable E has no value

[13]> (exp 1)
2.7182817


[14]> (log pi)
1.1447298858494001742L0

[15]> (log 8 2)        ; base-2 log
3

[16]> (log 100 10)     ; log is base-10 by default
2

[17]> (expt 25 0.5)    ; (expt base power)
5.0

; Lisp handles numbers greater than 2^262144 (via Peter Seibel)
[18]> (expt 2 262144)
Evaluating Expressions
$ clisp -q

; evaluate: 237 + 24 / 8
[1]> (+ 237 (/ 24 8))  
240

; evaluate:  240 + 14 * 2 / 4 - 7
[2]> (- (+ 240 (/ (* 14 2) 4)) 7)
240

; evaluate:  2 * (22 % 7)
[3]> (* 2 (mod 22 7))
2

; evaluate:  f(x) = 15 + 86(x)  when x = 4
[4]> (+ 15 (* 86 4))
359

; convert 240 Kelvin to degree Fahrenheit: 240 x (9/5) - 459.67
[5]> (- (* 240 (/ 9 5.0)) 459.67)
-27.670013

; calculate the golden ratio (phi):  (1 + sqrt(5)) / 2
[6]> (/ (+ 1 (sqrt 5)) 2)
1.618034

; calculate the average of min { 1 2 3 } and max { 4 5 6 }
[7]> (/ (+ (min 1 2 3) (max 4 5 6)) 2)
7/2

[8]> (/ (+ (min 1 2 3) (max 4 5 6)) 2.0)
3.5

; triple the sum of -2, 0, 5
[9]> (* 3 (+ -2 0 5))
9

; evaluate:  4^3 - 3^2 + 3^4
[10]> (+ (- (expt 4 3) (expt 3 2)) (expt 3 4))
136

; evaluate Avogardo number:  6.022140857 * 10^23
[12]> (* 6.022140857 (expt 10 23))
6.022141E23

; evaluate Plank constant:  6.62607004 * 10^-34
[13]> (* 6.62607004 (expt 10 -34))
6.62607E-34

; evaluate Plank constant and store in a variable
[14]> (setf plank (* 6.62607004 (expt 10 -34)))
6.62607E-34

; evaluate f(x) = 3x^2 - 5x + 2 when x = 2
[15]> (setf x 2)
[15]> (+ 2 (- (* 3 (expt x 2)) (* 5 x)))
4

; evaluate g(x) = x^3 - 6x^2 + 11x - 6
[16]> (setf x 3)
[16]> (+ (expt x 3) (* -6 (expt x 2)) (* 11 x) -6)
0

; evaluate:  5^2 + 5 * 2 - 4 / 2^2
[17]> (+ (expt 5 2) (* 5 2) (/ -4 (expt 2 2)))
34

; evaluate:  (2 * (4 + (5 + 3)))
[18]> (* 2 (+ 4 (+ 5 3)))
24

; evaluate:  (4 + 6) - ((((8 / 4) - 1) * 6))
[19]> (- (+ 4 6) (* (- (/ 8 4) 1) 6))
4

; evaluate:  ((8 / 4) + 6) - (2 * (9 - 8))
[20]> (- (+ (/ 8 4) 6) (* 2 (- 9 8)))
6

; format Plank constant as a string using FORMAT function
[21]> (format nil "~f" plank)
"0.000000000000000000000000000000000662607"

; print Plank constant to standard output stream using FORMAT function
[22]> (format t "~f" plank) 
0.000000000000000000000000000000000662607
NIL

{TopOfPage} {Resources}


Lisp Programs Stored in a File

The following was excuted using BASH on a Linux system. In BASH, # starts a comment that ends at end-of-line.

$ vim hw.lisp    # lisp code inserted into hw.lisp using vim text editor

$ ls             # lisp code stored in a dot-lisp file
hw.lisp

$ cat hw.lisp    # display contents of hw.lisp
;;; 
;;; This Lisp program prints the phrase "hello world"
;;; followed by a newline to the standard output stream.
;;;

(write "hello, world")

$ clisp -q -c hw.lisp   # submit file to the clisp compiler
;; Compiling file /home/gdt/lisp/src/hw.lisp ...
;; Wrote file /home/gdt/lisp/src/hw.fas
0 errors, 0 warnings

$ ls                    # dot-fas (bytecode) and dot-lib files created
hw.fas   hw.lib   hw.lisp

$ clisp hw              # execute the program using clisp
"hello, world"

$ clisp hw | od -c      # 'od' (octal dump) to see newline character
0000000   "   h   e   l   l   o   ,       w   o   r   l   d   "  \n
0000017

But... the phrase "hello, world" should not include double quotes.

$ vi hw2.lisp

$ cat hw2.lisp
(format t "~a" "hello, world")

$ clisp -q -c hw2.lisp
;; Compiling file /home/gdt/lisp/src/hw2.lisp ...
;; Wrote file /home/gdt/lisp/src/hw2.fas
0 errors, 0 warnings

$ clisp hw2
hello, world

$ clisp hw2 | od -c
0000000   h   e   l   l   o   ,       w   o   r   l   d  \n
0000015

{TopOfPage} {Resources}


Relational Functions

The relational functions (=, /=, <, >, <=, >=) evaluate to NIL to T.

$ clisp -q
[1]> (= 3 5)
NIL

[2]> (/= 3 5)
T

[3]> (> 3 5)
NIL

[4]> (< 3 5)
T

[5]> (>= 3 5)
NIL

[6]> (<= 3 5)
T

[7]> (= 5 5 5 5)
T

[8]> (= 5 5 2 5)
NIL

[9]> (/= 5 5 5 5)
NIL

[10]> (/= 5 4 8 2)
T

[11]> (/= 5 4 5 2)
NIL

[12]> (< 2 3 5 9)
T

[13]> (< 2 5 3 9)
NIL

[14]> (> 9 5 3 0)
T

[15]> (> 9 3 5 0)
NIL

[16]> (< 2 5 5 8)
NIL

[17]> (<= 2 5 5 8)
T

[18]> (> 3 2 2 1)
NIL

[19]> (>= 3 2 2 1)
T

; hmm...

[20]> (= 5)
T

[21]> (= 0)
T

[22]> (/= 5)
T

[23]> (/= 0)
T

[24]> (> 3)
T

; what about strings?

[25]> (= "foo" "foo")
*** - =: "foo" is not a number

; eq, eql, equal, equalp will be covered later...
; nutshell:
;    + eq compares addresses, while equal compares content
;    + never use eq to compare numbers
;    + eql is the "standard" comparison predicate

[26]> (eql 3 3)
T

[27]> (eql 3 2)
NIL

[28]> (equal 3 2)
NIL

[29]> (equal 3 3)
T

[30]> (eql 3 3.0)     ; different types... use =
NIL

[31]> (= 3 3.0)
T

[32]> (equal "Foo" "foo")
NIL

[33]> (equal "foo" "foo")
T

[34]> (eq "foo" "foo")    ; eq compares addresses
NIL

{TopOfPage} {Resources}


IF (Special) Function

IF takes at least two arguments: test true-part. A third argument can be a false-part.

[21]> (if t 'true 'false)
TRUE

[22]> (if nil 'true 'false)
FALSE

[23]> (if (oddp 240) 'odd 'even)
EVEN

[24]> (if (= 3 5) 'equal '!equal)
!EQUAL

[25]> (if (= 3 3) 'equal '!equal)
EQUAL

[26]> (defvar x 0)
X

[27]> (if (= 3 3) (setf x "3 equals 3") (setf x ("3 != 3")))
"3 equals 3"

[28]> (princ x)
"3 equals 3" 
"3 equals 3"

; "If you need to put more than one statement in the then or else 
;  clause of an if statement, you can use the progn special form. 
;  Progn executes each statement in its body, then returns the value 
;  of the final one." -- via n-a-n-o.com

[13] (setf x 3)
3

[14]> (if (= x 3) (progn (setq y x) (setq z x)))
3

[15]> x
3

[16]> y
3

[17]> z
3

{TopOfPage} {Resources}


COND (Macro) Function

Syntax:

   (cond (test-form-1 eval-form-1)
         (test-form-2 eval-form-2)
         (test-form-3 eval-form-3)
         ...
         (test-form-n eval-form-n))
[1]> (cond ((= 3 5) 'equal) 
           ((> 3 5) 'gt)
           ((< 3 5) 'lt))
LT

[3]> (setf a 5 b 4 c 3 d 2)
2

; incorrrect code...
; [8]> (cond ((> a b) (and (= a 5))) 'yes 'no)
; T
; [9]> (cond ((> a b) (and (/= a 5))) 'yes 'no)
; NIL
; [11]> (cond ((> a b) (and (not (= a c)))) 'yes 'no)
; T

[8]> (setf a 5 b 4 c 3 d 2)
2

[9]> (cond ((and (> a b) (= a 5)) 'yes))
YES

[10]> (cond ((and (> a b) (/= a 5)) 'no))
NIL

[11]> (cond ((and (> a b) (/= a 5)) 'no) (t 'yes))
YES

[12]> (cond ((and (> a b) (not (= a c))) 'yes) (t 'no))
YES

[17]> (defun state (s) (cond ((equal s 'az) 'arizona)
                             ((equal s 'ar) 'arkansas)
                             ((equal s 'ak) 'alaska)
                             ((equal s 'al) 'alabama)
                             (t "don't know")))

[47]> (state 'az)
ARIZONA

[48]> (state 'ar)
ARKANSAS

[49]> (state 'ak)
ALASKA

[50]> (state 'nm)
"don't know"

[51]> (defun foo (c) (cond 
             ((string= c "foo") 'isfoo) 
             ((string= c "goo") 'isgoo)
             (t "!foo and !goo")))
FOO

[52]> (foo "foo")
ISFOO

[53]> (foo "goo")
ISFOO

[54]> (foo "moo")
"!foo and !goo"

{TopOfPage} {Resources}


DRIBBLE Function

The DRIBBLE function enables a Lisp session to be captured in a file.

[1]> (dribble "dribble.txt")

;; Dribble of # started on 2016-11-02 06:21:25.
#

[2]> (cons 1 2)
(1 . 2)

[3]> (car '(1 2 3))
1

[4]> (cdr '(1 2 3))
(2 3)

[5]> (bye)
Bye.

{TopOfPage} {Resources}


FORMAT function

AI.MIT.edu::Function FORMAT | Formatted Output

GigaMonkeys.com::Common Practical Lisp::A Few FORMAT Recipes

$ clisp -q

[1]> (setq p (* 6.022141 (expt 10 23)))
6.022141E23

[2]> (format t "~:d" p)
6.022141E23
NIL

[3]> (format t "~:f" p)
602214100000000000000000.0
NIL

[4]> (setq p2 602214100000000000000000)
602214100000000000000000

[5]> (format t "~:d" p2)
602,214,100,000,000,000,000,000
NIL

[6]> (format nil "~r" 240)
"two hundred and forty"

[7]> (format t "~@r" 240)
CCXL

[8]> (format t "~S~%" "hello")   ; ~% does newline  ~n% does n newlines
"hello"

[9]> (format t "~S~3%" "hello")   ; ~% does newline  ~n% does n newlines
"hello"


[10] t
NIL

; added 02016.11.08

[9]> (setf first "Zelmo")
"Zelmo"

[10]> (setf last "Zeroman")
"Zeroman"

[11]> (setf full (format nil "~a, ~a" last first))
"Zeroman, Zelmo"

[12]> full
"Zeroman, Zelmo"

[13]> (format t "~a~4%" full)
Zeroman, Zelmo



NIL


[14]> (format nil "~a~4%" full)
"Zeroman, Zelmo



"

[15]> (format t "~3%~a~3%" full)



Zeroman, Zelmo


NIL

[16] (format t "~~~a" full)    ; use ~~ to get a ~
~Zeroman, Zelmo
NIL

{TopOfPage} {Resources}


QUOTE Function

The arguments to the QUOTE function do not get evaluated. The apostrophe is an alias for QUOTE.

[1]> (quote foo)
FOO

[2]> foo
*** - SYSTEM::READ-EVAL-PRINT: variable FOO has no value

[3]> 'foo
FOO

[4]> (list (quote 1) (quote 2) (quote 3))
(1 2 3)

[5]> (list '1 '2 '3)
(1 2 3)

[6]> (list '(1 2 3))
((1 2 3))

[7]> (list (quote (1 2 3)))
((1 2 3))

{TopOfPage} {Resources}


CAR and CDR Functions

[1]> (car '(1 2 3))
1

[2]> (cdr '(1 2 3))
(2 3)

[3]> (setf alist '(1 2 3))
(1 2 3)

[4]> (car alist)
1

[5]> (cdr alist)
(2 3)

[6]> (setf alist '((1 2 3 4) (5 6 7 8)))
((1 2 3 4) (5 6 7 8))

[7]> (car alist)
(1 2 3 4)

[8]> (cdr alist)
((5 6 7 8))

[9]> (caar alist)
1

[10]> (caaar alist)
*** - CAAAR: alist is not a list

[11]> (setf blist '((1 2) (3 4) (4 5)))
((1 2) (3 4) (4 5))

[12]> (car blist)
(1 2)

[13]> (caar blist)
1

[14]> (cadr blist)
(3 4)

[15]> (cadar blist)
2

{TopOfPage} {Resources}


CONS Function

The CONS function creates "cons" cells. It takes two arguments: The first argument is the car() of the cons cell and the second argument is its cdr(). CONS is short for CONStruct. [Note: C++ and Java have "constructors."]

[1]> (cons 'hello 'world)    ; results in a dotted-pair 
(HELLO . WORLD)

;; cons cell:  car_pointer-+            cdr_pointer-+
;;                         |                        |
;;                         +-> hello                +-> world

[2]> (setf hw (cons 'hello 'world))
(HELLO . WORLD)

;; page 58 "Common Lisp: Gentle Introduction to Sybolic Computation"
;; x = CONS of (CAR of x) and (CDR of x)      [non-empty lists only]

[3]> (car hw)
HELLO

[4]> (cdr hw)
WORLD

[5]> (cons 'hello (cons 'world nil))
(HELLO WORLD)

; construct the list (1 2 3) using cons...
[6]> (cons 1 (cons 2 (cons 3 nil)))
(1 2 3)

; the LIST function creates lists using a bunch of elements
[7]> (list 1 2 3)
(1 2 3)

{TopOfPage} {Resources}


Lists and Related Functions

Lists are one-way chains of pointers (singly linked-list).

$ clisp -q
[1]> (setf e ())     ; () is an empty list
NIL

[2]> (listp e)       ; list predicate function
T

[3]> (length e)
0

[4]> (equal e nil)   ; nil is an empty list
T

[5]> (equal e '(red green blue))
NIL

[6]> (setf f nil)
NIL

[7]> (equal e f)
T

[8]> (listp f)
T

[9]> (equal f ())
T

[10]> (setf fib (list 0 1 1 2 3 5 8 13 21 34 55 89))
(0 1 1 2 3 5 8 13 21 34 55 89)

[11]> (length fib)
12

[12]> (if (listp fib) "is a list" "not a list")
"is a list"

[13]> (format t "~a" fib)
(0 1 1 2 3 5 8 13 21 34 55 89)

[14]> (car fib)
0

[15]> (first fib)
0

[16]> (if (= (second fib) (third fib)) 'yes 'no)
YES

[17]> (cdr fib)
(1 1 2 3 5 8 13 21 34 55 89)

[18]> (rest fib)
(1 1 2 3 5 8 13 21 34 55 89)

[19]> (if (= (car fib) (first fib)) 'yes 'no)
YES

[20]> (if (= (cdr fib) (rest fib)) 'yes 'no)
*** - =: (1 1 2 3 5 8 13 21 34 55 89) is not a number

[21]> (if (equal (cdr fib) (rest fib)) 'yes 'no)
YES

[22]> (last fib)          ; notice that last evals to a list
(89)

[23]> (car (last fib))
89

[24]> (cddr fib)
(1 2 3 5 8 13 21 34 55 89)

[25]> (cdddr fib)
(2 3 5 8 13 21 34 55 89)

[26]> (cddddr fib)
(3 5 8 13 21 34 55 89)

[27]> (cdddddr fib)        ; c....r  (at most 4 a's and d's)
*** - EVAL: undefined function CDDDDDR

[28]> (cadr fib)
1

[29]> (caddr fib)
1

[30]> (cadddr fib)
2

[31]> (if (= (cadddr fib) (fourth fib)) 'yes 'no)
YES

[32]> (setf x '( (c c++ java) (python perl php ruby) (lisp prolog)))
((C C++ JAVA) (PYTHON PERL PHP RUBY) (LISP PROLOG))

[33]> (car x)
(C C++ JAVA)

[34]> (cdar x)
(C++ JAVA)

[35]> (caar x)
C

[36]> (cadar x)
C++

[37]> (caddar x)
JAVA

[38]> (cdr x)
((PYTHON PERL PHP RUBY) (LISP PROLOG))

[39]> (cadr x)
(PYTHON PERL PHP RUBY)

[40]> (caadr x)
PYTHON

[41]> (second (cadr x))
PERL

[42]> (cdadr x)
(PERL PHP RUBY)

[43]> (caddr x)
(LISP PROLOG)

[43]> (caaddr x)
LISP

[44]> (last x)
((LISP PROLOG))

[45]> (last (first (last x)))
(PROLOG)

[46]> (first (last (first (last x))))
PROLOG

[47]> (setf alist (list (list 1 2 3) 4 5 6 (list 7 8 9)))
((1 2 3) 4 5 6 (7 8 9))

; reset...

[1]> (setf alist '( a b c d e f g h i))
(A B C D E F G H I)

[2]> (nthcdr 0 alist)     ; make a dup list? (setf l2 (nthcdr 0 l))
(A B C D E F G H I)       ; (equal l l2) => T

[3]> (nthcdr 1 alist)     ; equals (cdr l)?
(B C D E F G H I)

[4]> (nthcdr 2 alist)
(C D E F G H I)

[5]> (nthcdr 6 alist)
(G H I)

[6]> (nth 4 alist)
E

[15]> (car (nthcdr 4 alist))
E

[16]> (reverse alist)
(I H G F E D C B A)

[17]> alist               ; notice that reverse did not change alist
(A B C D E F G H I)

[18]> (last alist)
(I)

[19]> (remove 'e alist)
(A B C D F G H I)

[20]> alist               ; notice that remove did not change alist
(A B C D E F G H I)

[21]> (append '(1 2 3) '(a b c))
(1 2 3 A B C)

[22]> (setf a (append '((1 yes) (0 no)) '((1 true) (0 false))))
((1 YES) (0 NO) (1 TRUE) (0 FALSE))

[23]> (length a)
4

; let's return to car and cdr...

[42]> (car a)
(1 YES)

[41]> (cdr a)
((0 NO) (1 TRUE) (0 FALSE))

[43]> (caar a)
1

[44]> (cddr a)
((1 TRUE) (0 FALSE))

[45]> (nthcdr 3 a)
((0 FALSE))

[46]> (nth 3 a)            ; the car of nthcdr 3
(0 FALSE)

CS.CMU.edu::Common Lisp the Language, 2nd Edition::15.2. Lists

{TopOfPage} {Resources}


WHEN and UNLESS

WHEN and UNLESS are useful when multiple evaluations must occur when tests are true.

[1]> (setf a t)
T

[2]> (when a "do b")
"do b"

[3]> (unless a "don't do b")
NIL

[4]> (setf a nil)
NIL

[5]> (when a "do b")
NIL

[6]> (unless a "don't do b")
"don't do b"

[7]> (setf x 10)
10

[8]> (unless (zerop x) (decf x))
9

[9]> x
9

[10]> (when (> 5 3) (setf a 6) (+ a 6))
12
[11]> (setf age 59 name "gerald")
"gerald"

[12]> age
59

[13]> (when (string= name "gerald") (and (= age 59)) 'is-a-gerald)
IS-A-GERALD 

; bug found while going over [13] during class...

[13 bug]> (setf age 39)
39

[13 bug]> (when (string= name "gerald") (and (= age 59)) 'is-a-gerald)
IS-A-GERALD

[13 fix]> (when (and (string= name "gerald") (= age 59)) 'is-a-gerald)
NIL

[13 fix]> (setf age 59)
59

[13 fix]> (when (and (string= name "gerald") (= age 59)) 'is-a-gerald)
IS-A-GERALD

[14]> (when t (setf x 3) (setf y 4) (setf z 5))
5

[15]> (format t "~d ~d ~d" x y z)
3 4 5

; added after 'if' was covered during class...
; "If you need to put more than one statement in the then or else 
;  clause of an if statement, you can use the progn special form. 
;  Progn executes each statement in its body, then returns the value 
;  of the final one." -- via n-a-n-o.com

[16]> (if (= x 3) (progn (setq y x) (setq z x)))
3

[17]> (format t "~d ~d ~d" x y z)
3 3 3

{TopOfPage} {Resources}


DEFUN (macro) Function

DEFUN is used to define functions.

Syntax: (defun function_name (0_or_more_parameters))

[1]> (defun add2(a b) (+ a b))
ADD2

[2]> (add2 110 240)
350

[3]> (defun circumference (r)   ; uses optional documentation string
      "calculates the circumference of a circle" 
      (* 2 pi r))
CIRCUMFERENCE

[4]> (documentation 'circumference 'function)
"calculates the circumference of a circle"

[5]> (circumference 5)
31.415926535897932385L0

[6]> (setf y 5)
5

[7]> (defun yy (x) (+ x y))
YY

[8]> (yy 2)
7

[9]> (defun yx (x) (* x y))
YX

[10]> (yx 2)
10

[11]> (defun echo () (write (read)))
LET and LET* Functions

The LET and LET* functions are used to define local variables

[6]> (defun avg (a b) (let ((sum (+ a b))) (setf y (/ sum 2.0))))
AVG

[7]> (avg 205 240)
222.5

[8]> y
222.5

[11]> (defun pctchg (new old) (let* 
      ((diff (- new old)) 
       (factor (/ diff old)) 
       (p (* factor 100.0))) 
      (setf y p)))
PCTCHG

[12]> (pctchg 2 1)
100.0

[13]> (pctchg 1 2)
-50.0

[14]> y 
-50.0

[15] (defun fib (n)
     "compute the nth Fibonacci number"
     (if (or (zerop n) (= n 1)) 1
     (let ((f1 (fib (- n 1)))
           (f2 (fib (- n 2))))
           (+ f1 f2))))

[16]> (fib 5)
8

[17]> (fib 3)
3

[18]> (defun nude (n)
      "determine if a number is a nude number"
      (let ((ndigits (1+ (floor (log n 10)))) (d 0) (m n))
      (dotimes (i ndigits)
         (setf d (mod m 10))
         (setf m (floor (/ m 10)))
         (if (zerop m) (return t))
         (if (and (/= d 0) (/= (rem n d) 0)) (return nil)))))

[19]> (load "nude.fas")
;; Loading file nude.fas ...
;; Loaded file nude.fas
T

[20]> (nude 17199)
T

[21]> (nude 7785)
NIL

[22]> (nude 99)
T

[23]> (nude 828)
NIL

[24]> (defun infloop ()
      "uses LOOP to pretend being an infinite loop"
      (let ((len 3) (cnt 1))
         (loop
            (format t "napping for ~d seconds~%" len)
            (sleep len)
            (if (zerop (mod len 2)) (decf len) (incf len))
            (when (= cnt 5) (format t "done napping") (return t))
            (incf cnt))))


[25]> (infloop)
napping for 3 seconds
napping for 4 seconds
napping for 3 seconds
napping for 4 seconds
napping for 3 seconds
done napping
T

MAPCAR (applicative) Operator

MAPCAR "applies" a function to each element in a list and creates a list of the evaluations.


[24]> (mapcar #'sqrt '(4 9 16 25))
(2 3 4 5)

[25]> (mapcar #'fib '(0 1 2 3 4 6 7))
(1 1 2 3 5 13 21)

[26]> (defun grade (p)
(if (>= p 90) 'A
(if (>= p 80) 'B
(if (>= p 70) 'C
(if (>= p 60) 'D 'F)))))
GRADE

[27]> (mapcar #'grade '(77 93 85 47 64))
(C A B F D)

{TopOfPage} {Resources}


SDRAW Tool

SDRAW draws cons cell structures. The code is from the book "Common Lisp: A Gentle Introduction to Symbolic Computation" by David S. Touretzky (Benjamin/Cummings Publishing Co., 1990).

[1]> (load "sdraw.fas")
;; Loading file sdraw.fas ...
;; Loaded file sdraw.fas
T

[2]> (sdraw (cons 4 5))

[*|*]--->5
 |
 v
 4

[3]> (sdraw '(1 2 3))

[*|*]--->[*|*]--->[*|*]--->NIL
 |        |        |
 v        v        v
 1        2        3

[4]> (sdraw '(to write in c or not to write in c))

[*|*]--->[*|*]--->[*|*]--->[*|*]--->[*|*]--->[*|*]--->[*|*]--->[*|*]--->etc.
 |        |        |        |        |        |        |        |
 v        v        v        v        v        v        v        v
 TO      WRITE     IN       C        OR      NOT       TO      WRITE

[5]> (sdraw '((hello world) (goodbye earth)))

   [*|*]------------------>[*|*]--->NIL
    |                       |
    v                       v
    [*|*]--->[*|*]--->NIL   [*|*]---->[*|*]--->NIL
     |        |              |         |
     v        v              v         v
    HELLO    WORLD          GOODBYE   EARTH

[6]> (sdraw '((1) 2 (3 4) 5))

[*|*]--------->[*|*]--->[*|*]------------------>[*|*]--->NIL
 |              |        |                       |
 v              v        v                       v
[*|*]--->NIL    2       [*|*]--->[*|*]--->NIL    5
 |                       |        |
 v                       v        v
 1                       3        4

{TopOfPage} {Resources}


Interation (Loops)

DOTIMES and DOLIST.

   (DOTIMES (loop-control-variable max [result-form]) body)

   (DOLIST (loop-control-variable max [result-form]) body)

The loop-control-variable goes from 0 to max-1.

[1]> (dotimes (i 5) (format t "~d " i))
0 1 2 3 4 

[2]> (setf x 1)
1

[3]> (dotimes (i 5) (setf x (* x (1+ i))))   ; 5! (factorial)
NIL

[4]> x
120

[14]> (dolist (element '(foo goo moo)) (format t "~a ... " element))
FOO ... GOO ... MOO ... 

[15]> (setf min 999999999999999999999999)
999999999999999999999999

[16]> (setf max -1)
-1

[17]> (dolist (n '(5 13 2 8 16 2 21 4)) 
(if (> n max) (setf max n)) 
(if (< n min) (setf min n)))
NIL

[18]> (list min max)
(2 21)

; similar to a 'break' in C/Java
[19]> (dotimes (n 10) (if (= n 5) (return n)))   
5

"DO is the most powerful iteration function in Lisp." -- "Common Lisp: A Gentle Introdution to Symbolic Computation.

The syntax for DO is non-trivial.

   ; via Common Lisp by David S. Touretsky; page 347

   (DO ( (var1 init1 [update1])
         (var2 init2 [update2])
           ...)
         (test action-1 ... action-n)
      body)

Here are some DO examples.

$ clisp -q

; countdown by two starting with 16; print "done" when 0 is reached
;
[1]> (do ((cnt 16 (- cnt 2))) 
         ((zerop cnt) (format t "done"))
          (format t "~d..." cnt))
16...14...12...10...8...6...4...2...done

[2]> (bye)

$ vi underline.lisp

(defun underline (s) 
   (format t "~a~%" s)
   (do ((len (length s) (decf len)))
       ((zerop len) nil)
           (format t "=")))

$ clisp -q -c underline.lisp
;; Compiling file /home/gdt/underline.lisp ...
;; Wrote file /home/gdt/underline.fas
0 errors, 0 warnings

$ clisp -q
[1]> (load "underline.fas")
;; Loading file underline.fas ...
;; Loaded file underline.fas
T

[2]> (underline "hello")
hello
=====

;; the next two functions are from the book Common Lisp: A Gentle 
;; Introduction to Symbolic Computation... (fact) is on page 349
;; and (read-a-number) is on page 352
;;
[3] (defun fact (n) (do ((i n (- i 1)) 
                         (result 1 (* result i)))
                         ((zerop i) result))))
FACT

[4]> (fact 5)
120

[5] (defun read-a-number () 
       (do ((n nil)) 
           (nil)
       (format t "~&Please type a number: ")
       (setf n (read))
       (if (numberp n)
           (return n))
       (format t "~&Sorry, ~S is not a number. Try again." n)))

[6]> (read-a-number)
Please type a number: foo
Sorry, FOO is not a number. Try again.
Please type a number: 240
240

;; goto [5]
;; ~& format: prints newline only if needed
;; ~% format: always emits a newline

There is also a LOOP macro that enables one to write Lisp code that is similar to C.

[1]> (loop for logname in '(dmr bs bwk gdt ken rms esr) 
        do (format t "~a" logname))  ; don't forget the in
DMRBSBWKGDTKENRMSESR

[2]> (setf x (loop for n from 0 to 10 when (evenp n) collect n))
(0 2 4 6 8 10)

[5]> (setf oddcnt (loop for n from 0 to 100 count (oddp n)))
50

[6]> (loop for n from -5 to 5 append (list n))
(-5 -4 -3 -2 -1 0 1 2 3 4 5)

CL-Cookbook.SourceForge.net::The Common List Cookbook - The Loop Macro

{TopOfPage} {Resources}


READ Function

The READ function can be used to read an "object" from the standard input stream.

[1]> (setf input (READ))
hello
HELLO

[2]> input
HELLO

[3]> (setf input (READ))
hello world
HELLO

[4]> 
*** - SYSTEM::READ-EVAL-PRINT: variable WORLD has no value

[5]> (setf input (READ))
"hello world"
"hello world"

[6]> input
"hello world"

[7]> (setf input (READ))
240
240

[8]> input
240

[9]> (setf input (READ))
3.14159265358979
3.1415927

[10]> input
3.1415927

[11]> (yes-or-no-p "do you want to play again?")
do you want to play again? (yes/no) no
NIL

[12]> (yes-or-no-p "do you want to play again?")
do you want to play again? (yes/no) yes
T

[13]> (yes-or-no-p "do you want to play again?")
do you want to play again? (yes/no) n
Please answer with yes or no : y
Please answer with yes or no : YES
T

[14]> (Y-OR-N-P "continue?")
continue? (y/n) y
T

{TopOfPage} {Resources}


Sets

A Lisp list can be a set. A set is an unordered collection of unique elements.

[37]> (setf lang '(c c++ java lisp prolog javascript r perl bash))
(C C++ JAVA LISP PROLOG JAVASCRIPT R PERL BASH)

[38]> (member 'cobol lang)
NIL

[39]> (member 'java lang)
(JAVA LISP PROLOG JAVASCRIPT R PERL BASH)

[40]> (setf cfamily '(c c++ java php))
(C C++ JAVA PHP)

[41]> (intersection cfamily lang)
(C C++ JAVA)

[42]> (union cfamily lang)
(PHP C C++ JAVA LISP PROLOG JAVASCRIPT R PERL BASH)

[43]> (set-difference cfamily lang)
(PHP)

[44]> (set-difference lang cfamily)
(LISP PROLOG JAVASCRIPT R PERL BASH)

[45]> (subsetp cfamily lang)
NIL

[46]> (subsetp lang cfamily)
NIL

{TopOfPage} {Resources}


Tables

A Lisp list can represent a table of key/value pairs.

[51]> (setf dow '((0 Sun) (1 Mon) (2 Tue) (3 Wed) (4 Thu) (5 Fri) (6 Sat)))
((0 SUN) (1 MON) (2 TUE) (3 WED) (4 THU) (5 FRI) (6 SAT))

[52]> (assoc '1 dow)
(1 MON)

[53]> (assoc '5 dow)
(5 FRI)

[54]> (assoc '8 dow)
NIL

[55]> (car (assoc '5 dow))
5

[56]> (setf who '((c dmr) (c++ stroustrup) (java gosling) (lisp mccarthy)))
((C DMR) (C++ STROUSTRUP) (JAVA GOSLING) (LISP MCCARTHY))

[57]> (assoc 'c who)
(C DMR)

[58]> (assoc 'cobol who)
NIL

[59]> (assoc 'lisp who)
(LISP MCCARTHY)

{TopOfPage} {Resources}


LAMBDA Expressions

LAMBDA creates an anonymous (nameless function).

Syntax note: #' quotes a function. #' is to FUNCTION as ' is to QUOTE.

[1]> (setf alist '(1 2 3 4 5))
(1 2 3 4 5)

[2]> #'(lambda (x) (setf (car x) 5))
#

[3]> (funcall * alist)
5

[4]> alist
(5 2 3 4 5)

[5]> #'(lambda (x) (setf (cdr x) '(4 3 2 1)))
#

[6]> (funcall * alist)
(4 3 2 1)

[7]> alist
(5 4 3 2 1)

[8]> (mapcar #'(lambda (x) (* x 2)) alist)
(10 8 6 4 2)

[9]> (setf why #'(lambda () 'y))
#

[10]> (funcall why)
Y

; we stray...

[11]> why
#

[12]> (why)
*** - EVAL: undefined function WHY

[13]> (functionp why)
T

[14]> (functionp 'why)
NIL

[15]> (functionp #'why)
*** - FUNCTION: undefined function WHY

[16]> car
*** - SYSTEM::READ-EVAL-PRINT: variable CAR has no value

[17]> (car)
*** - EVAL: too few arguments given to CAR: (CAR)

[18]> (functionp 'car)
NIL

[19]> (functionp #'car)
T

[20]> (functionp (function car))
T

[21]> (functionp (function why))
*** - FUNCTION: undefined function WHY

{TopOfPage} {Resources}


Arrays

Lisp supports arrays from 1 to 'n' dimensions.

[1]> (make-array 5)
#(NIL NIL NIL NIL NIL)

[2]> (make-array 5 :initial-element -1)
#(-1 -1 -1 -1 -1)

[5]> (setf a (make-array 10 :element-type 'integer 
                       :initial-contents '(0 1 2 3 4 5 6 7 8 9)))
#(0 1 2 3 4 5 6 7 8 9)

[6]> (car a)
*** - CAR: #(0 1 2 3 4 5 6 7 8 9) is not a list

[7]> (setf digits (make-array 10 :initial-contents '(9 8 7 6 5 4 3 2 1 0)))
#(9 8 7 6 5 4 3 2 1 0)

[8]> (dotimes (i (length digits)) (format t "~d " (aref digits i)))
9 8 7 6 5 4 3 2 1 0 

[9]> (setf x (make-array 3))
#(NIL NIL NIL)

[10]> (setf (aref x 0) "foo")
"foo"

[11]> x
#("foo" NIL NIL)

[12]> (setf (aref x 2) "goo")
"goo"

[13]> x
#("foo" NIL "goo")

[14]> (aref x 5)
*** - AREF: index 5 for #("foo" NIL "goo") is out of range

[15]> (aref x -2)
*** - AREF: index -2 for #("foo" NIL "goo") is not of type `(INTEGER 0

[16]> (adjust-array x 5)
#("foo" NIL "goo" NIL NIL)

[17]> (length x)
3

[18]> (setf x (adjust-array x 5))
#("foo" NIL "goo" NIL NIL)

[19]> (length x)
5

; I found bit arrays interesting...

[20]> (setf bits (make-array 8 :element-type 'bit))
#*00000000

[21]> bits
#*00000000

[22]> (bit-ior bits #*00101000)  ; inclusive or
#*00101000

[23]> (bit-xor bits #*00101000)  ; exclusive or
#*00101000

[24]> (bit-nand bits #*00101000)
#*11111111

[25]> (bit-nor bits #*00101000)
#*11010111

[26]> (bit-not #*0101 #*1100)
#*1010

;;; decided to write a program...
;;; http://azfoo.net/gdt/csc240/lisp/src/bitarrays.lisp

(defvar a (make-array 4 :element-type 'bit :initial-contents #*0101))
(defvar b (make-array 4 :element-type 'bit :initial-contents #*1100))

(dolist (fn '(bit-and bit-ior bit-xor bit-eqv bit-nand bit-nor
              bit-andc1 bit-andc2 bit-orc1 bit-orc2 bit-not))
	  (format t "(~a ~a ~a) ==> ~a~%" fn a b (funcall fn a b))

; captured output...

(BIT-AND #*0101 #*1100) ==> #*0100
(BIT-IOR #*0101 #*1100) ==> #*1101
(BIT-XOR #*0101 #*1100) ==> #*1001
(BIT-EQV #*0101 #*1100) ==> #*0110
(BIT-NAND #*0101 #*1100) ==> #*1011
(BIT-NOR #*0101 #*1100) ==> #*0010
(BIT-ANDC1 #*0101 #*1100) ==> #*1000
(BIT-ANDC2 #*0101 #*1100) ==> #*0001
(BIT-ORC1 #*0101 #*1100) ==> #*1110
(BIT-ORC2 #*0101 #*1100) ==> #*0111
(BIT-NOT #*0101 #*1010) ==> #*1010

; strings are arrays...

[50]> (defun spacey-string (s) (dotimes (i (length s)) (format t "~S" (aref s i))))
SPACEY-STRING

[51]> (spacey-string "hello")
#\h#\e#\l#\l#\o

[53]> (defun spacey-string (s) (dotimes (i (length s)) (format t "~c" (aref s i))))
SPACEY-STRING

[54]> (spacey-string "hello")
hello

[55]> (defun spacey-string (s) (dotimes (i (length s)) (format t "~c " (aref s i))))
SPACEY-STRING

[56]> (spacey-string "hello")
h e l l o 

cl-cookbook.sourceforge.net::Strings

{TopOfPage} {Resources}


STRUCT Function

STRUCT enables the programmer to define a "record."

   (defstruct person
      name
      address
      zipcode
      age)

   Every "person" is an object with four pieces of data.

   The following accessor functions are defined:
      (person-fieldname some-person-object)

   The (make-person) constructor is defined.
[1]> (defstruct person name age)
PERSON

[2]> (setf p (make-person))
#S(PERSON :NAME NIL :AGE NIL)

[3]> (typep p 'person)
T

[4]> (person-name p)
NIL

[5]> (person-age p)
NIL

[6]> (setf p (make-person :name "Zelmo Zeroman" :age 42))
#S(PERSON :NAME "Zelmo Zeroman" :AGE 42)

[7]> (person-name p)
"Zelmo Zeroman"

[8]> (person-age p)
42

[9]> (setf (person-age p) 21)
21

{TopOfPage} {Resources}


Date and Time

; from The Common Lisp Cookbook
; "Universal time is represented as the number of seconds that have 
;  elapsed since 00:00 of January 1, 1900 in the GMT time zone.  Time 
;  1 is 00:00:01 (that is, 12:00:01 a.m.) on January 1, 1900 GMT. 
;
; "Day of the week is represented as an integer in the range 
;  0..6 with 0 being Monday and 6 being Sunday." -- This is
;  not consistent with what I said during class.
;
; struct tm in time.h:
; C: tm_mon... month of the year (from 0)
;    tm_year... years since 1900 (from 0)
;    tm_wday... days since Sunday (from 0)
;
[12]> (get-universal-time)
3688372090

; current time using C on Unix: 
; 1479388654 seconds (Thu Nov 17 06:17:34 2016)
; time_t 3688372090 ==> Sun Nov 17 04:48:10 2086


; second, minute, hour, date, month, year, day, daylight-p, zone
[15]> (decode-universal-time (get-universal-time))
48 ;
48 ;
4 ;
17 ;
11 ;
2016 ;
3 ;
NIL ;
7

; second, minute, hour, date, month, year, day, daylight-p, zone
; executed in timezone MST-7
[16]> (get-decoded-time)
12 ;
49 ;
4 ;
17 ;
11 ;
2016 ;
3 ;
NIL ;
7

; second minute hour day month year &optional timezone
[19]> (encode-universal-time 0 52 4 17 11 2016)
3688372320

{TopOfPage} {Resources}


The CSC240 Resources Webpage
Books

C++: SEAS.Harvard.edu::Thinking in C++ by Bruce Eckel

Lisp: CS.CMU.edu::COMMON LISP: A Gentle Introduction to Symbolic Computation by David S. Touretzky
Lisp: GigaMonkeys.com::Practical Common Lisp by Peter Seibel
Lisp: CS.CMU.edu::Common Lisp the Language, 2nd Edition
Lisp: cl-cookbook.sourceforge.net::The Common Lisp Cookbook
Lisp: LispWorks.com::Common Lisp HyperSpec

Prolog: LearnPrologNow.org::Learn Prolog Now!
Prolog: CDN.preterhuman.net::The Art of Prolog by Leon Sterling and Ehud Shapiro
Prolog: gprolog.org::manual::GNU Prolog (gprolog001)

Tutorials

C++: CPlusPlus.com | TutorialsPoint.com

Lisp: TutorialsPoint.com
Lisp: PaulGraham.com::lisp.html
Lisp: CS.sfu.ca::Learning Lisp for CMPT 310

Prolog: LearnPrologNow.org
Prolog: NewThinkTank.com::Learn Prolog In One Video
Prolog: Prolog-Heritage.org::Prolog Heritage

CodingGround

TutorialsPoint.com::CodingGround::C++ | Lisp | Prolog

{TopOfPage} {Resources}


Hello, World

I am using gprolog (GNU Prolog) to learn about Prolog.

| ?- is the gprolog prompt.

Statements end with a period (.) and % starts a comment that ends at the end of the line.

halt. is used to exit gprolog.

Prolog programs are stored in files that end in either dot-pl, dot-pro, or dot-P.

$ gprolog       # shell command-line

GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz

| ?- write('hello, world'), nl, write('prolog--logic programming').
hello, world
prolog--logic programming

yes

| ?- halt.

$ edit mcccd.pl     # and type in a knowledge base
$ cat mcccd.pl

mcccd('Maricopa County Community College District').
campus(scc).
campus(mcc).
campus(gcc).

$ gprolog

| ?- [mcccd].    % load knowledge base; could do: consult('mcccd.pl').

compiling /home/gdt/prolog/mcccd.pl for byte code...
/home/gdt/prolog/mcccd.pl compiled, 4 lines read - 576 bytes written, 7 ms

yes

| ?- campus(scc).

yes
| ?- campus(foo).

no

| ?- listing(mcccd).

mcccd('Maricopa County Community College District').

yes

| ?- listing(campus).

campus(scc).
campus(mcc).
campus(gcc).

yes

| ?- campus(X).

X = scc ? ;

X = mcc ? ;

X = gcc

yes

| ?- foo = foo.

yes

| ?- foo = goo.

no

| ?- 3 > 5.

no

| ?- 5 > 3.

yes
| ?- 3 <= 5.
uncaught exception: error(syntax_error('user_input:18 (char:3) . or operator expected after expression'),read_term/3)

| ?- 3 =< 5.

yes


| ?- 3 \= 5.

yes

| ?- 3 \= 3.

no


| ?- 5 =:= 3.

no


| ?- 5 =:= 5.

yes

| ?- 5 =\= 3.

yes


| ?- X is 1 + 1.

X = 2

yes

| ?- X is 5 / 2.

X = 2.5

yes

| ?- X is 5 / 0.
uncaught exception: error(evaluation_error(zero_divisor),(is)/2)


| ?- X is 1 + (2 * 3).

X = 7

yes

| ?- (3 * 5) > (3 + 5).

yes

| ?- (3 * 5) > (5 * 3).

no




| ?- 5 == X.

no
| ?- X is 2 + 3.

X = 5

yes

| ?- 5 =:= X.
uncaught exception: error(instantiation_error,(=:=)/2)

| ?- 5 = X.

X = 5

yes

| ?- random(1,5,X.
Prolog interruption (h for help) ? c
).
uncaught exception: error(syntax_error('user_input:30 (char:13) , or ) expected'),read_term/3)

| ?- random(1,5,X).

X = 4

yes

| ?- X is abs(-3).

X = 3

yes

| ?- X is min(5,10).

X = 5

yes

| ?- X is max(5,10).

X = 10

yes

| ?- 


| ?- X is abs(-3).

X = 3

yes

| ?- X is min(5,10).

X = 5

yes

| ?- X is max(5,10).

X = 10

yes

| ?- X is round(3.1416).

X = 3

yes

| ?- X is floor(3.1416).

X = 3

yes

| ?- X is truncated(3.1416).
uncaught exception: error(type_error(evaluable,truncated/1),(is)/2)

| ?- X is truncate(3.1416).

X = 3

yes

| ?- X is ceiling(3.1416).

X = 4

yes

| ?- X is 2^3.

X = 1

yes

| ?- X is 2**3.

X = 8.0

yes


| ?- atom(X).

no

| ?- atom(x).

yes

| ?- atom('x').

yes

| ?- atom("x").

no

| ?- atom(_x).

no

| ?- X is sqrt(25).

X = 5.0

| ?- X is sqrt(-1).

X = -nan


yes
| ?- X is 5 ** 2.

X = 25.0

yes

| ?- X is exp(1).

X = 2.7182818284590451

| ?- X is log(exp(1)).

X = 1.0

yes
Day 2...

About ^ in gprolog...

| ?- X is 2^3.

X = 1

yes

% hmm... ^ is not power (exponent)

| ?- X is 5^2.

X = 7

yes

| ?- X is 1^3.

X = 2

yes

% hmm... ^ appears to be bit-wise exclusive or... 
% but, let's consult the documentation...

% copy/paste from gprolog.org/manual
% "An arithmetic expression is a Prolog term built from numbers, 
%  variables, and functors (or operators) that represent arithmetic 
%  functions. When an expression is evaluated each variable must be 
%  bound to a non-variable expression. An expression evaluates to a 
%  number, which may be an integer or a floating point number. The 
%  following table details the components of an arithmetic expression, 
%  how they are evaluated, the types expected/returned and if they are 
%  ISO or an extension:" [long table presented]
%
%  expression  Result=eval(Expression)                  Signature      ISO
%  =======================================================================
%  xor(E1,E2)   eval(E1) bitwise_xor eval(E2)            I, I -> I       Y 
%  E1 ^ E2      eval(E1) raised to the power of eval(E2) IF, IF -> IF    Y 
%  E1 ** E2     eval(E1) raised to the power of eval(E2) IF, IF -> IF    Y 
%
%  goto('gprolog.org/manual/gprolog.html#sec98').

| ?- X is xor(5, 2).
uncaught exception: error(type_error(evaluable,xor/2),(is)/2)

% D'OH!

% resume...

| ?- X is 5 >> 1.

X = 2

yes
| ?- X is 5 << 1.

X = 10

yes

% lists...

| ?- [1,2,3,4] = [H|T].

H = 1
T = [2,3,4]

| ?- [1] = [H|T].

H = 1
T = []

yes

| ?- [] = [H|T].

no

| ?- [foo, goo, moo] = [Car | Cddr].

Car = foo
Cddr = [goo,moo]

yes


ling /home/gdt/gdt/csc240/prolog/lisp.pl for byte code...
/home/gdt/gdt/csc240/prolog/lisp.pl:1: warning: singleton variables [T] for car/2
/home/gdt/gdt/csc240/prolog/lisp.pl:2: warning: singleton variables [H] for cdr/2
/home/gdt/gdt/csc240/prolog/lisp.pl compiled, 2 lines read - 488 bytes written, 6 ms

yes

| ?- car([1,2,3],X).

X = 1

yes

| ?- cdr([1,2,3],Y).

Y = [2,3]

yes

| ?- halt.

{TopOfPage} {Resources}


Prolog Interactions by Alain Colmerauer

Alain.Colmerauer.free.fr::From natural language processing to Prolog (Beijing, April 8, 2011)

   INPUT TEXT:
      KAYSER WORKS IN PARIS.
      EVERY PERSONNE WHO WORKS IN PARIS, TAKES THE UNDERGROUND.
      KAYSER IS A PERSON.
   query:
      WHAT DOES KAYSER TAKE?

   ANSWER:
      +SORT(THE UNDERGROUND) ;.

   INPUT TEXT:
      THE ICE IS A SOLID.
      EVERY SOLID WHICH MELTS, IS A LIQUID.
      KAYSER DRINKS ICE WHICH MELTS.

   query:
      WHO DRINKS A LIQUID?
      DOES KAYSER DRINKS A LIQUID?

   ANSWER:
      +SORT(KAYSER) ;.
      +SORT(YES) ;.

   INPUT TEXT:
      THE MONDE INFORMS EVERY FELLOW WHO READS IT.
      THE PRESIDENT IS A FELLOW.

   query:
      WHO READS THE MONDE?
      WHOM DOES INFORM THE MONDE?

   ANSWER:
      +SORT(THE PRESIDENT) ;.
      +SORT(THE PRESIDENT) ;.


The progam about brother and sister

   brothersister(X,Z) :- issonof(X,Y), isdaughterof(Z,Y).
   isdaughterof(helen,judith).
   isdaughterof(nicole,mary).
   isdaughterof(rachel,mary).
   issonof(jules,judith).
   issonof(paul,judith).
   issonof(robert,mary).

   First execution
   > brothersister(paul,X)?
   X=helen.

   Second execution
   > brothersister(X,helen)?
   X=jules.
   X=paul.

   First execution, details
   > brothersister(paul,X)?
      brothersister(X1,Z1) :- issonof(X1,Y1), isdaughterof(Z1,Y1).
      X1=paul, X=Z1
   > issonof(paul,Y1), isdaughterof(Z1,Y1)?
      issonof(paul,judith).
      Y1=judith.
   > isdaughterof(Z1,judith)?
      isdaughterof(helen,judith).
      Z1=helen
      X=helen

   Second execution, details
   > brothersister(X,helen)?
      brothersister(X1,Z1) :- issonof(X1,Y1), isdaughterof(Z1,Y1).
      X=X1, Z1=helen
   > issonof(X1,Y1), isdaughterof(helen,Y1)?
      issonof(jule,judith).
      X1=jule, Y1=judith
   > isdaughterof(helen,judith)?
      isdaughterof(helen,judith).
      X=jule
      issonof(paul,judith).
      X1=paul, Y1=judith
   > isdaughterof(helen,judith)?
      isdaughterof(helen,judith).
      X=paul
      issonof(robert,mary).
      X1=robert, Y1=mary
   > isdaughterof(helen,judith)?
      isdaughterof(helen,mary).

{TopOfPage} {Resources}


Brother and Sister

Entered Alain Colmerauer's brother and sister program into gprolog via a file named bs.pl.

| ?- [bs].
compiling /home/gdt/prolog/bs.pl for byte code...
/home/gdt/prolog/bs.pl compiled, 7 lines read - 1152 bytes written, 9 ms

yes
| ?- brothersister(jules, helen).

yes
| ?- brothersister(jules, nicole).

| ?- isdaughterof(helen,mary).

no
| ?- isdaughterof(helen,judith).

yes
| ?- isdaughterof(helen,Mom).   

Mom = judith

yes
| ?- isdaughterof(Kid,mary).

Kid = nicole ? ;

Kid = rachel

yes

| ?- brothersister(jules,helen).

yes
| ?- brothersister(paul,helen).

yes

| ?- brothersister(paul, Sister).

Sister = helen ? ;

no
| ?- brothersister(X, helen).

X = jules ? ;

X = paul ? ;

no

% added to bs.pl...
% ismom(ismom(X,Y) :- issonof(X,Y); isdaughterof(X,Y).

| ?- ismom(X, judith).

X = jules ? ;

X = paul ? ;

X = helen ? ;

no

{TopOfPage} {Resources}


Home Previous Next