mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 17:41:41 +00:00
Fixes based on pkh's comments.
This commit is contained in:
parent
082dffc697
commit
f39aa6adfb
@ -71,16 +71,21 @@ t ; another atom, denoting true.
|
|||||||
|
|
||||||
;;; Symbols
|
;;; 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 "AAAA") ; => AAAA
|
||||||
|
|
||||||
|
(intern "aaa") ; => |aaa|
|
||||||
|
|
||||||
;;; Numbers
|
;;; Numbers
|
||||||
9999999999999999999999 ; integers
|
9999999999999999999999 ; integers
|
||||||
#b111 ; binary => 7
|
#b111 ; binary => 7
|
||||||
#o111 ; octal => 73
|
#o111 ; octal => 73
|
||||||
#x111 ; hexadecimal => 273
|
#x111 ; hexadecimal => 273
|
||||||
3.14159 ; floating point
|
3.14159s0 ; single
|
||||||
|
3.14159d0 ; double
|
||||||
1/2 ; ratios
|
1/2 ; ratios
|
||||||
#C(1 2) ; complex numbers
|
#C(1 2) ; complex numbers
|
||||||
|
|
||||||
@ -104,7 +109,7 @@ t ; another atom, denoting true.
|
|||||||
|
|
||||||
;;; Booleans
|
;;; Booleans
|
||||||
t ; for true (any not-nil value is true)
|
t ; for true (any not-nil value is true)
|
||||||
nil ; for false
|
nil ; for false - and the empty list
|
||||||
(not nil) ; => t
|
(not nil) ; => t
|
||||||
(and 0 t) ; => t
|
(and 0 t) ; => t
|
||||||
(or 0 nil) ; => 0
|
(or 0 nil) ; => 0
|
||||||
@ -114,21 +119,21 @@ nil ; for false
|
|||||||
#\λ ; => #\GREEK_SMALL_LETTER_LAMDA
|
#\λ ; => #\GREEK_SMALL_LETTER_LAMDA
|
||||||
#\u03BB ; => #\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!"
|
"Hello, world!"
|
||||||
"Benjamin \"Bugsy\" Siegel" ; backslash is an escaping character
|
"Benjamin \"Bugsy\" Siegel" ; backslash is an escaping character
|
||||||
|
|
||||||
;; Strings can be concatenated too!
|
;; Strings can be concatenated too!
|
||||||
(concatenate 'string "Hello " "world!") ; => "Hello world!"
|
(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
|
(elt "Apple" 0) ; => #\A
|
||||||
|
|
||||||
;; format can be used to format strings:
|
;; format can be used to format strings:
|
||||||
(format nil "~a can be ~a" "strings" "formatted")
|
(format nil "~a can be ~a" "strings" "formatted")
|
||||||
|
|
||||||
;; Printing is pretty easy
|
;; Printing is pretty easy; ~% is the format specifier for newline.
|
||||||
(format t "Common Lisp is groovy. Dude.\n")
|
(format t "Common Lisp is groovy. Dude.~%")
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -136,15 +141,19 @@ nil ; for false
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; You can create a global (dynamically scoped) using defparameter
|
;; You can create a global (dynamically scoped) using defparameter
|
||||||
;; a variable name can use any character except: ()[]{}",'`;#|\
|
;; a variable name can use any character except: ()[]{}",'`;#|\
|
||||||
|
|
||||||
|
;; Dynamically scoped variables should have earmuffs in their name!
|
||||||
|
|
||||||
(defparameter *some-var* 5)
|
(defparameter *some-var* 5)
|
||||||
*some-var* ; => 5
|
*some-var* ; => 5
|
||||||
|
|
||||||
;; You can also use unicode characters. Not very easy to use though...
|
;; You can also use unicode characters.
|
||||||
(defparameter *foo#\u03BBooo* nil)
|
(defparameter *AΛB* nil)
|
||||||
|
|
||||||
|
|
||||||
;; Accessing a previously unassigned variable is an undefined
|
;; Accessing a previously unbound variable is an
|
||||||
;; behavior (but possible). Don't do it.
|
;; undefined behavior (but possible). Don't do it.
|
||||||
|
|
||||||
|
|
||||||
;; Local binding: `me` is bound to "dance with you" only within the
|
;; 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 ...). Let always returns the value of the last `form` in the
|
||||||
@ -165,9 +174,12 @@ nil ; for false
|
|||||||
:breed "collie"
|
:breed "collie"
|
||||||
:age 5))
|
:age 5))
|
||||||
*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5)
|
*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5)
|
||||||
|
|
||||||
(dog-p *rover*) ; => t ;; ewww)
|
(dog-p *rover*) ; => t ;; ewww)
|
||||||
(dog-name *rover*) ; => "rover"
|
(dog-name *rover*) ; => "rover"
|
||||||
|
|
||||||
|
;; Dog-p, make-dog, and dog-name are all created by defstruct!
|
||||||
|
|
||||||
;;; Pairs
|
;;; Pairs
|
||||||
;; `cons' constructs pairs, `car' and `cdr' extract the first
|
;; `cons' constructs pairs, `car' and `cdr' extract the first
|
||||||
;; and second elements
|
;; and second elements
|
||||||
@ -188,12 +200,16 @@ nil ; for false
|
|||||||
;; Can still use `cons' to add an item to the beginning of a list
|
;; Can still use `cons' to add an item to the beginning of a list
|
||||||
(cons 4 '(1 2 3)) ; => '(4 1 2 3)
|
(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)
|
(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:
|
;; them, a few examples:
|
||||||
(mapcar #1+ '(1 2 3)) ; => '(2 3 4)
|
(mapcar #'1+ '(1 2 3)) ; => '(2 3 4)
|
||||||
(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33)
|
(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33)
|
||||||
(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4)
|
(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4)
|
||||||
(every #'evenp '(1 2 3 4)) ; => nil
|
(every #'evenp '(1 2 3 4)) ; => nil
|
||||||
@ -217,60 +233,96 @@ nil ; for false
|
|||||||
|
|
||||||
(make-array (list 2 2))
|
(make-array (list 2 2))
|
||||||
|
|
||||||
|
;; (make-array '(2 2)) works as well.
|
||||||
|
|
||||||
; => #2A((0 0) (0 0))
|
; => #2A((0 0) (0 0))
|
||||||
|
|
||||||
(make-array (list 2 2 2))
|
(make-array (list 2 2 2))
|
||||||
|
|
||||||
; => #3A(((0 0) (0 0)) ((0 0) (0 0)))
|
; => #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)
|
(aref (make-array (list 2 2 2)) 1 1 1)
|
||||||
|
|
||||||
; => 0
|
; => 0
|
||||||
|
|
||||||
;;; Sets are just lists:
|
;;; Naively, sets are just lists:
|
||||||
|
|
||||||
(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1)
|
(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1)
|
||||||
(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4
|
(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)
|
(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)
|
(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.
|
;;; Dictionaries are implemented as hash tables.
|
||||||
|
|
||||||
;; Create a hash table
|
;; Create a hash table
|
||||||
(defparameter m (hash-table))
|
(defparameter *m* (make-hash-table))
|
||||||
|
|
||||||
;; set a value
|
;; set a value
|
||||||
(setf (gethash 'a hash-table 1))
|
(setf (gethash 'a *m*) 1)
|
||||||
|
|
||||||
;; Retrieve a value
|
;; Retrieve a value
|
||||||
(gethash 'a m) ; => 1
|
(gethash 'a *m*) ; => 1, t
|
||||||
|
|
||||||
;; Retrieving a non-present value returns a nil
|
;; Detail - Common Lisp has multiple return values possible. gethash
|
||||||
(gethash m 'd) ;=> nil
|
;; 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
|
;; 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
|
;; 3. Functions
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; Use `lambda' to create anonymous functions.
|
;; Use `lambda' to create anonymous functions.
|
||||||
;; A function always returns the value of its last expression
|
;; A function always returns the value of its last expression.
|
||||||
(lambda () "Hello World") ; => #<function>
|
;; The exact printable representation of a function will vary...
|
||||||
|
|
||||||
|
(lambda () "Hello World") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}>
|
||||||
|
|
||||||
;; Use funcall to call lambda functions
|
;; Use funcall to call lambda functions
|
||||||
(funcall (lambda () "Hello World")) ; => "Hello World"
|
(funcall (lambda () "Hello World")) ; => "Hello World"
|
||||||
|
|
||||||
|
;; Or Apply
|
||||||
|
(apply (lambda () "Hello World") nil) ; => "Hello World"
|
||||||
|
|
||||||
;; De-anonymize the function
|
;; De-anonymize the function
|
||||||
(defun hello-world () "Hello World")
|
(defun hello-world ()
|
||||||
|
"Hello World")
|
||||||
(hello-world) ; => "Hello World"
|
(hello-world) ; => "Hello World"
|
||||||
|
|
||||||
;; The () in the above is the list of arguments for the function
|
;; The () in the above is the list of arguments for the function
|
||||||
(defun hello (name)
|
(defun hello (name)
|
||||||
(format nil "Hello, ~a " name))
|
(format nil "Hello, ~a " name))
|
||||||
|
|
||||||
(hello "Steve") ; => "Hello, Steve"
|
(hello "Steve") ; => "Hello, Steve"
|
||||||
|
|
||||||
;; Functions can have optional arguments; they default to nil
|
;; Functions can have optional arguments; they default to nil
|
||||||
@ -286,6 +338,12 @@ nil ; for false
|
|||||||
(defun hello (name &optional (from "The world"))
|
(defun hello (name &optional (from "The world"))
|
||||||
(format t "Hello, ~a, from ~a" name from))
|
(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
|
;; And of course, keywords are allowed as well... usually more
|
||||||
;; flexible than &optional.
|
;; flexible than &optional.
|
||||||
@ -302,18 +360,18 @@ nil ; for false
|
|||||||
;; 4. Equality
|
;; 4. Equality
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; Common Lisp has a sophisticated equality system.
|
;; Common Lisp has a sophisticated equality system. A couple are covered yere.
|
||||||
|
|
||||||
;; for numbers use `='
|
;; for numbers use `='
|
||||||
(= 3 3.0) ; => t
|
(= 3 3.0) ; => t
|
||||||
(= 2 1) ; => nil
|
(= 2 1) ; => nil
|
||||||
|
|
||||||
;; for object identity (approximately) use `eq?'
|
;; for object identity (approximately) use `eql`
|
||||||
(eql 3 3) ; => t
|
(eql 3 3) ; => t
|
||||||
(eql 3 3.0) ; => nil
|
(eql 3 3.0) ; => nil
|
||||||
(eql (list 3) (list 3)) ; => 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 'a 'b)) ; => t
|
||||||
(equal (list 'a 'b) (list 'b 'a)) ; => nil
|
(equal (list 'a 'b) (list 'b 'a)) ; => nil
|
||||||
|
|
||||||
@ -352,7 +410,7 @@ nil ; for false
|
|||||||
;; Of course recursion is supported:
|
;; Of course recursion is supported:
|
||||||
|
|
||||||
(defun walker (n)
|
(defun walker (n)
|
||||||
(if (= n 0)
|
(if (zerop 0)
|
||||||
:walked
|
:walked
|
||||||
(walker (1- n))))
|
(walker (1- n))))
|
||||||
|
|
||||||
@ -380,8 +438,8 @@ nil ; for false
|
|||||||
;; demonstrated earlier in the hash table example.
|
;; demonstrated earlier in the hash table example.
|
||||||
|
|
||||||
(let ((variable 10))
|
(let ((variable 10))
|
||||||
(setf variable 10))
|
(setf variable 2))
|
||||||
; => 10
|
; => 2
|
||||||
|
|
||||||
|
|
||||||
;; Good Lisp style is to minimize destructive functions and to avoid
|
;; Good Lisp style is to minimize destructive functions and to avoid
|
||||||
@ -403,6 +461,15 @@ nil ; for false
|
|||||||
:initarg :average-efficiency)
|
:initarg :average-efficiency)
|
||||||
(:documentation "A human powered conveyance"))
|
(: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)
|
(defclass bicycle (human-powered-conveyance)
|
||||||
((wheel-size
|
((wheel-size
|
||||||
:accessor wheel-size
|
:accessor wheel-size
|
||||||
@ -424,6 +491,7 @@ nil ; for false
|
|||||||
:accessor number-of-rowers
|
:accessor number-of-rowers
|
||||||
:initarg :number-of-rowers)))
|
:initarg :number-of-rowers)))
|
||||||
|
|
||||||
|
|
||||||
;; Calling DESCRIBE on the human-powered-conveyance class in the REPL gives:
|
;; Calling DESCRIBE on the human-powered-conveyance class in the REPL gives:
|
||||||
|
|
||||||
(describe 'human-powered-conveyance)
|
(describe 'human-powered-conveyance)
|
||||||
@ -438,7 +506,7 @@ nil ; for false
|
|||||||
; Direct superclasses: STANDARD-OBJECT
|
; Direct superclasses: STANDARD-OBJECT
|
||||||
; Direct subclasses: UNICYCLE, BICYCLE, CANOE
|
; Direct subclasses: UNICYCLE, BICYCLE, CANOE
|
||||||
; Not yet finalized.
|
; Not yet finalized.
|
||||||
; Direct slots:
|
(defparameter *foo#\u03BBooo* nil) ; Direct slots:
|
||||||
; VELOCITY
|
; VELOCITY
|
||||||
; Readers: VELOCITY
|
; Readers: VELOCITY
|
||||||
; Writers: (SETF VELOCITY)
|
; Writers: (SETF VELOCITY)
|
||||||
@ -450,10 +518,12 @@ nil ; for false
|
|||||||
;; designed to be an interactive system
|
;; designed to be an interactive system
|
||||||
|
|
||||||
;; To define a method, let's find out what our circumference of the
|
;; 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))
|
(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
|
;; 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
|
;; of rowers in a canoe is roughly logarithmic. This should probably be set
|
||||||
@ -488,7 +558,7 @@ nil ; for false
|
|||||||
`condition` is tested prior to each execution of `body`"
|
`condition` is tested prior to each execution of `body`"
|
||||||
(let ((block-name (gensym)))
|
(let ((block-name (gensym)))
|
||||||
`(tagbody
|
`(tagbody
|
||||||
(when (not ,condition)
|
(unless ,condition
|
||||||
(go ,block-name))
|
(go ,block-name))
|
||||||
(progn
|
(progn
|
||||||
,@body)
|
,@body)
|
||||||
@ -503,13 +573,14 @@ nil ; for false
|
|||||||
`condition` is tested prior to each execution of `body`"
|
`condition` is tested prior to each execution of `body`"
|
||||||
`(loop while ,condition
|
`(loop while ,condition
|
||||||
do
|
do
|
||||||
,@body))
|
(progn
|
||||||
|
,@body)))
|
||||||
|
|
||||||
;; However, with a modern compiler, this is not required; the LOOP
|
;; However, with a modern compiler, this is not required; the LOOP
|
||||||
;; form compiles equally well and is easier to read.
|
;; form compiles equally well and is easier to read.
|
||||||
|
|
||||||
;; Note that ` is used, as well as , and @. ` is a quote-type operator
|
;; Note that ``` is used, as well as `,` and `@`. ``` is a quote-type operator
|
||||||
;; known as quasiquote; it allows the use of ,. , allows "unquoting"
|
;; known as quasiquote; it allows the use of `,` . `,` allows "unquoting"
|
||||||
;; variables. @ interpolates lists.
|
;; variables. @ interpolates lists.
|
||||||
|
|
||||||
;; Gensym creates a unique symbol guaranteed to not exist elsewhere in
|
;; 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
|
Lots of thanks to the Scheme people for rolling up a great starting
|
||||||
point which could be easily moved to Common Lisp.
|
point which could be easily moved to Common Lisp.
|
||||||
|
|
||||||
|
- [Paul Khoung](https://github.com/pkhuong) for some great reviewing.
|
||||||
|
Loading…
Reference in New Issue
Block a user