summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorpdn <pnathan@vandals.uidaho.edu>2013-08-11 10:39:13 -0700
committerpdn <pnathan@vandals.uidaho.edu>2013-08-11 10:39:13 -0700
commitf39aa6adfb98086e98773f7871c3ba70f97c5771 (patch)
tree7aa1ec4ac9ff4600f24c2a14be94d3077d1badff
parent082dffc69714418456966bd7932f8e1b1fc8fcb0 (diff)
Fixes based on pkh's comments.
-rw-r--r--common-lisp.html.markdown251
1 files changed, 162 insertions, 89 deletions
diff --git a/common-lisp.html.markdown b/common-lisp.html.markdown
index 757b6a14..9f2c9957 100644
--- a/common-lisp.html.markdown
+++ b/common-lisp.html.markdown
@@ -71,16 +71,21 @@ t ; another atom, denoting true.
;;; Symbols
-'foo ; => FOO
+'foo ; => FOO Notice that the symbol is upper-cased automatically.
+
+;; Intern manually creates a symbol from a string.
(intern "AAAA") ; => AAAA
+(intern "aaa") ; => |aaa|
+
;;; Numbers
9999999999999999999999 ; integers
#b111 ; binary => 7
#o111 ; octal => 73
#x111 ; hexadecimal => 273
-3.14159 ; floating point
+3.14159s0 ; single
+3.14159d0 ; double
1/2 ; ratios
#C(1 2) ; complex numbers
@@ -93,42 +98,42 @@ t ; another atom, denoting true.
;; You can also call a function manually:
(funcall #'+ 1 2 3) ; => 6
;; Some arithmetic operations
-(+ 1 1) ; => 2
-(- 8 1) ; => 7
-(* 10 2) ; => 20
-(expt 2 3) ; => 8
-(mod 5 2) ; => 1
-(/ 35 5) ; => 7
-(/ 1 3) ; => 1/3
+(+ 1 1) ; => 2
+(- 8 1) ; => 7
+(* 10 2) ; => 20
+(expt 2 3) ; => 8
+(mod 5 2) ; => 1
+(/ 35 5) ; => 7
+(/ 1 3) ; => 1/3
(+ #C(1 2) #C(6 -4)) ; => #C(7 -2)
-;;; Booleans
-t ; for true (any not-nil value is true)
-nil ; for false
-(not nil) ; => t
-(and 0 t) ; => t
-(or 0 nil) ; => 0
+ ;;; Booleans
+t ; for true (any not-nil value is true)
+nil ; for false - and the empty list
+(not nil) ; => t
+(and 0 t) ; => t
+(or 0 nil) ; => 0
-;;; Characters
-#\A ; => #\A
-#\λ ; => #\GREEK_SMALL_LETTER_LAMDA
-#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA
+ ;;; Characters
+#\A ; => #\A
+#\λ ; => #\GREEK_SMALL_LETTER_LAMDA
+#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA
-;;; Strings are fixed-length simple-arrays of characters.
+;;; Strings are fixed-length arrays of characters.
"Hello, world!"
"Benjamin \"Bugsy\" Siegel" ; backslash is an escaping character
;; Strings can be concatenated too!
(concatenate 'string "Hello " "world!") ; => "Hello world!"
-;; A string can be treated like a list of characters
+;; A string can be treated like a sequence of characters
(elt "Apple" 0) ; => #\A
;; format can be used to format strings:
(format nil "~a can be ~a" "strings" "formatted")
-;; Printing is pretty easy
-(format t "Common Lisp is groovy. Dude.\n")
+;; Printing is pretty easy; ~% is the format specifier for newline.
+(format t "Common Lisp is groovy. Dude.~%")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -136,22 +141,26 @@ nil ; for false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; You can create a global (dynamically scoped) using defparameter
;; a variable name can use any character except: ()[]{}",'`;#|\
+
+;; Dynamically scoped variables should have earmuffs in their name!
+
(defparameter *some-var* 5)
*some-var* ; => 5
-;; You can also use unicode characters. Not very easy to use though...
-(defparameter *foo#\u03BBooo* nil)
+;; You can also use unicode characters.
+(defparameter *AΛB* nil)
-;; Accessing a previously unassigned variable is an undefined
-;; behavior (but possible). Don't do it.
+;; Accessing a previously unbound variable is an
+;; undefined behavior (but possible). Don't do it.
+
;; Local binding: `me` is bound to "dance with you" only within the
;; (let ...). Let always returns the value of the last `form` in the
;; let form.
(let ((me "dance with you"))
- me)
+ me)
;; => "dance with you"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -165,9 +174,12 @@ nil ; for false
:breed "collie"
:age 5))
*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5)
+
(dog-p *rover*) ; => t ;; ewww)
(dog-name *rover*) ; => "rover"
+;; Dog-p, make-dog, and dog-name are all created by defstruct!
+
;;; Pairs
;; `cons' constructs pairs, `car' and `cdr' extract the first
;; and second elements
@@ -188,17 +200,21 @@ nil ; for false
;; Can still use `cons' to add an item to the beginning of a list
(cons 4 '(1 2 3)) ; => '(4 1 2 3)
-;; Use `append' to add lists together
+;; Use `append' to - surprisingly - append lists together
(append '(1 2) '(3 4)) ; => '(1 2 3 4)
-;; Lists are a very basic type, so there is a wide variety of functionality for
+;; Or use concatenate -
+
+(concatenate
+
+;; Lists are a very central type, so there is a wide variety of functionality for
;; them, a few examples:
-(mapcar #1+ '(1 2 3)) ; => '(2 3 4)
-(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33)
-(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4)
-(every #'evenp '(1 2 3 4)) ; => nil
-(some #'oddp '(1 2 3 4)) ; => T
-(butlast '(subject verb object)) ; => (SUBJECT VERB)
+(mapcar #'1+ '(1 2 3)) ; => '(2 3 4)
+(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33)
+(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4)
+(every #'evenp '(1 2 3 4)) ; => nil
+(some #'oddp '(1 2 3 4)) ; => T
+(butlast '(subject verb object)) ; => (SUBJECT VERB)
;;; Vectors
@@ -217,60 +233,96 @@ nil ; for false
(make-array (list 2 2))
+;; (make-array '(2 2)) works as well.
+
; => #2A((0 0) (0 0))
(make-array (list 2 2 2))
; => #3A(((0 0) (0 0)) ((0 0) (0 0)))
+;; Caution- the default initial values are
+;; implementation-defined. Here's how to define them:
-; access the element at 1,1,1,
+(make-array '(2) :initial-element 'unset)
+
+; => #(UNSET UNSET)
+
+;; And, to access the element at 1,1,1 -
(aref (make-array (list 2 2 2)) 1 1 1)
; => 0
-;;; Sets are just lists:
+;;; Naively, sets are just lists:
(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1)
(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4
(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7)
(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4)
+;; But you'll want to use a better data structure than a linked list
+;; for performant work!
+
;;; Dictionaries are implemented as hash tables.
;; Create a hash table
-(defparameter m (hash-table))
+(defparameter *m* (make-hash-table))
;; set a value
-(setf (gethash 'a hash-table 1))
+(setf (gethash 'a *m*) 1)
;; Retrieve a value
-(gethash 'a m) ; => 1
+(gethash 'a *m*) ; => 1, t
-;; Retrieving a non-present value returns a nil
- (gethash m 'd) ;=> nil
+;; Detail - Common Lisp has multiple return values possible. gethash
+;; returns t in the second value if anything was found, and nil if
+;; not.
+
+;; Retrieving a non-present value returns nil
+ (gethash *m* 'd) ;=> nil, nil
;; You can provide a default value for missing keys
-(gethash m 'd :not-found) ; => :NOT-FOUND
+(gethash *m* 'd :not-found) ; => :NOT-FOUND
+
+;; Let's handle the multiple return values here in code.
+
+(multiple-value-bind
+ (a b)
+ (gethash 'd *m*)
+ (list a b))
+; => (NIL NIL)
+
+(multiple-value-bind
+ (a b)
+ (gethash 'a *m*)
+ (list a b))
+; => (1 T)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 3. Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Use `lambda' to create anonymous functions.
-;; A function always returns the value of its last expression
-(lambda () "Hello World") ; => #<function>
+;; A function always returns the value of its last expression.
+;; The exact printable representation of a function will vary...
+
+(lambda () "Hello World") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}>
;; Use funcall to call lambda functions
(funcall (lambda () "Hello World")) ; => "Hello World"
+;; Or Apply
+(apply (lambda () "Hello World") nil) ; => "Hello World"
+
;; De-anonymize the function
-(defun hello-world () "Hello World")
+(defun hello-world ()
+ "Hello World")
(hello-world) ; => "Hello World"
;; The () in the above is the list of arguments for the function
(defun hello (name)
- (format nil "Hello, ~a " name))
+ (format nil "Hello, ~a " name))
+
(hello "Steve") ; => "Hello, Steve"
;; Functions can have optional arguments; they default to nil
@@ -286,6 +338,12 @@ nil ; for false
(defun hello (name &optional (from "The world"))
(format t "Hello, ~a, from ~a" name from))
+(hello "Steve")
+; => Hello, Steve, from The world
+
+(hello "Steve" "the alpacas")
+; => Hello, Steve, from the alpacas
+
;; And of course, keywords are allowed as well... usually more
;; flexible than &optional.
@@ -302,18 +360,18 @@ nil ; for false
;; 4. Equality
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Common Lisp has a sophisticated equality system.
+;; Common Lisp has a sophisticated equality system. A couple are covered yere.
;; for numbers use `='
(= 3 3.0) ; => t
(= 2 1) ; => nil
-;; for object identity (approximately) use `eq?'
+;; for object identity (approximately) use `eql`
(eql 3 3) ; => t
(eql 3 3.0) ; => nil
(eql (list 3) (list 3)) ; => nil
-;; for collections use `equal'
+;; for lists, strings, and bit-vectors use `equal'
(equal (list 'a 'b) (list 'a 'b)) ; => t
(equal (list 'a 'b) (list 'b 'a)) ; => nil
@@ -342,8 +400,8 @@ nil ; for false
;; Typecase switches on the type of the value
(typecase 1
- (string :string)
- (integer :int))
+ (string :string)
+ (integer :int))
; => :int
@@ -352,9 +410,9 @@ nil ; for false
;; Of course recursion is supported:
(defun walker (n)
- (if (= n 0)
- :walked
- (walker (1- n))))
+ (if (zerop 0)
+ :walked
+ (walker (1- n))))
(walker) ; => :walked
@@ -362,12 +420,12 @@ nil ; for false
(dolist (i '(1 2 3 4))
- (format t "~a" i))
+ (format t "~a" i))
; => 1234
(loop for i from 0 below 10
- collect i)
+ collect i)
; => (0 1 2 3 4 5 6 7 8 9)
@@ -380,8 +438,8 @@ nil ; for false
;; demonstrated earlier in the hash table example.
(let ((variable 10))
- (setf variable 10))
- ; => 10
+ (setf variable 2))
+ ; => 2
;; Good Lisp style is to minimize destructive functions and to avoid
@@ -395,34 +453,44 @@ nil ; for false
;; Conveyances.
(defclass human-powered-conveyance ()
- ((velocity
- :accessor velocity
- :initarg :velocity)
- (average-efficiency
- :accessor average-efficiency)
- :initarg :average-efficiency)
- (:documentation "A human powered conveyance"))
+ ((velocity
+ :accessor velocity
+ :initarg :velocity)
+ (average-efficiency
+ :accessor average-efficiency)
+ :initarg :average-efficiency)
+ (:documentation "A human powered conveyance"))
+
+;; defclass, followed by name, followed by the superclass list,
+;; followed by slot list, followed by optional qualities such as
+;; :documentation.
+
+;; When no superclass list is set, the empty list defaults to the
+;; standard-object class. This *can* be changed, but not until you
+;; know what you're doing. Look up the Art of the Metaobject Protocol
+;; for more information.
(defclass bicycle (human-powered-conveyance)
- ((wheel-size
- :accessor wheel-size
- :initarg :wheel-size
- :documentation "Diameter of the wheel.")
- (height
- :accessor height
- :initarg :height)))
+ ((wheel-size
+ :accessor wheel-size
+ :initarg :wheel-size
+ :documentation "Diameter of the wheel.")
+ (height
+ :accessor height
+ :initarg :height)))
(defclass recumbent (bicycle)
- ((chain-type
- :accessor chain-type
- :initarg :chain-type)))
+ ((chain-type
+ :accessor chain-type
+ :initarg :chain-type)))
(defclass unicycle (human-powered-conveyance) nil)
(defclass canoe (human-powered-conveyance)
- ((number-of-rowers
- :accessor number-of-rowers
- :initarg :number-of-rowers)))
+ ((number-of-rowers
+ :accessor number-of-rowers
+ :initarg :number-of-rowers)))
+
;; Calling DESCRIBE on the human-powered-conveyance class in the REPL gives:
@@ -438,7 +506,7 @@ nil ; for false
; Direct superclasses: STANDARD-OBJECT
; Direct subclasses: UNICYCLE, BICYCLE, CANOE
; Not yet finalized.
-; Direct slots:
+(defparameter *foo#\u03BBooo* nil) ; Direct slots:
; VELOCITY
; Readers: VELOCITY
; Writers: (SETF VELOCITY)
@@ -450,14 +518,16 @@ nil ; for false
;; designed to be an interactive system
;; To define a method, let's find out what our circumference of the
-;; bike turns out to be using the equation: C = d * pi
+;; bike wheel turns out to be using the equation: C = d * pi
(defmethod circumference ((object bicycle))
- (* 3.14159 (wheel-size object)))
+ (* pi (wheel-size object)))
+
+;; pi is defined in Lisp already for us!
;; Let's suppose we find out that the efficiency value of the number
-;; of rowers in a canoe is roughly logarithmic. This should probably be set
-;; in the constructor/initializer.
+;; of rowers in a canoe is roughly logarithmic. This should probably be set
+;; in the constructor/initializer.
;; Here's how to initialize your instance after Common Lisp gets done
;; constructing it:
@@ -488,7 +558,7 @@ nil ; for false
`condition` is tested prior to each execution of `body`"
(let ((block-name (gensym)))
`(tagbody
- (when (not ,condition)
+ (unless ,condition
(go ,block-name))
(progn
,@body)
@@ -503,13 +573,14 @@ nil ; for false
`condition` is tested prior to each execution of `body`"
`(loop while ,condition
do
- ,@body))
+ (progn
+ ,@body)))
;; However, with a modern compiler, this is not required; the LOOP
;; form compiles equally well and is easier to read.
-;; Note that ` is used, as well as , and @. ` is a quote-type operator
-;; known as quasiquote; it allows the use of ,. , allows "unquoting"
+;; Note that ``` is used, as well as `,` and `@`. ``` is a quote-type operator
+;; known as quasiquote; it allows the use of `,` . `,` allows "unquoting"
;; variables. @ interpolates lists.
;; Gensym creates a unique symbol guaranteed to not exist elsewhere in
@@ -529,3 +600,5 @@ nil ; for false
Lots of thanks to the Scheme people for rolling up a great starting
point which could be easily moved to Common Lisp.
+
+- [Paul Khoung](https://github.com/pkhuong) for some great reviewing.