본문 바로가기

LISP?

sucessful lisp


LIST 와 ATOM : 유연성의 설명, 리스트에서 데이타와 프로그램이 혼재할 수 있다는 점
a form : 평가될 수 있는 형태, 값이 평가되는 것이면 리스트와 아톰 모두 form이 될 수 있다
a symbol: 값을 가진 상수인 아톰 그 자체
: 패키지 접두어(prefix)인 키워드 심볼을 나타냄
a form이 리스트 이면 첫번째 요소는 symbol(함수명)이거나 lambda expression이라 불리는 special form이 된다.
prefix notation 방식을 따른다: 함수명을 문두에 쓰는 방식
(function argument1 argument2 argument3 ...)
numbers are self-evaluated.
predicate란: 참 또는 거짓을 반환할 수 있는 명제(진술)을 말한다.

Lisp always does the same thing to evaluate a list form:

  1. Evaluate the arguments, from left to right.
  2. Get the function associated with the first element.
  3. Apply the function to the arguments.

*FEATURES* : 이미 내장된(정의된) 리스프 변수
미리 정의되지 않은 symbol을 내면 닐!

(VALUES .....) form


Essential Evaluation





(setq my-name "David")
(setq a-variable 57)

(setq a-variable :a-keyword)
SETQ's first argument is a symbol. This is not evaluated. The second argument is assigned as the variable's value. SETQ returns the value of its last argument.
The SETQ form can actually take any even number of arguments, which should be alternating symbols and values:
SETQ performs the assignments from left to right, and returns the rightmost value.
(setq month "June" day 8 year 1954)
-> 1954


(let ((a 3)
(b 4)
(c 5))
(* (+ a b) c))
-> 35

? a
->| Error: Unbound variable
The LET form uses nested lists, but because it's a special form, only certain elements get evaluated.
None of the variables defined in the LET have a value after Lisp has finished evaluating the form.

In general, LET looks like this:

(let (bindings) forms)
where bindings is any number of two-element lists -- each list containing a symbol 
and a value -- and forms is any number of Lisp forms.
Unlike SETQ, which assigns values in left-to-right order,
LET binds variables all at the same time:
Lisp has a variation of LET, called LET*, that does perform bindings in order: 
? (setq u 37)
-> 37

? (let* ((v 4)
(u v))
(+ u v))
-> 8

The COND macro lets you evaluate Lisp forms conditionally.
? (let ((a 1)
(b 2)
(c 1)
(d 1))
(cond ((eql a b) 1)
((eql a c) "First form" 2)
((eql a d) 3)))
-> 2
COND is more general than the special form, IF, which only allows one test
and one form each for the then and else parts.

Conventional use of COND uses T as the test form in the final clause.
This guarantees that the body forms of the final clause get evaluated
if the tests fail in all of the other clauses. You can use the last clause
to return a default value or perform some appropriate operation. Here's an example:

? (let ((a 32))
(cond ((eql a 13) "An unlucky number")
((eql a 99) "A lucky number")
(t "Nothing special about this number")))
-> "Nothing special about this number"

QUOTE

Sometimes we'd like to suppress Lisp's normal evaluation rules.

One such case is when we'd like a symbol to stand for itself ,

rather than its value, when it appears as an argument of a function call:

(QUOTE form) eqv 'form


CONS

CONS is the most basic constructor of lists. It is a function,
so it evaluates both of its arguments. The second argument must be a list or NIL.

? (cons 1 nil)
-> (1)

? (cons 2 (cons 1 nil))
-> (2 1)

CONS adds a new item to the beginning of a list. The empty list is equivalent to NIL,

() eqv NIL
? (cons 1 ())
-> (1)
The fact that NIL evaluates to itself, combined with () eqv NIL,
means that you can write () rather than (QUOTE ()). Otherwise, Lisp would have to
make an exception to its evaluation rule to handle the empty list.


LIST

As you may have noticed, building a list out of nested CONS forms can be a
bit tedious. The LIST form does the same thing in a more perspicuous manner:

? (list 1 2 3)
-> (1 2 3)

LIST can take any number of arguments. Because LIST is a function,
it evaluates its arguments:

? (list 1 2 :hello "there" 3)
-> (1 2 :HELLO "there" 3)

FIRST and REST

If you think of a list as being made up of two parts -- the first element and
everything else -- then you can retrieve any individual element of a list
using the two operations, FIRST and REST.

? (setq my-list (quote (1 2 3 4 5)))
-> (1 2 3 4 5)

? (first my-list)
-> 1
? (rest my-list)
-> (2 3 4 5)
FIRST and REST are fairly recent additions to Lisp, renaming the equivalent
functions CAR and CDR, respectively. CAR and CDR got their names from an
implementation detail of one of the earliest Lisp implementations,
and the names persisted for decades despite the fact that the underlying
implementation had long since changed.

Naming and Identity
A symbol is just a name. It can stand for itself. Symbols are a data
type distinct from the objects they might be used to name.

A symbol is always unique. Every time your program uses a symbol,
that symbol is identical to every other symbol with the same name.
You can use the EQ test to compare symbols:

? (eq 'a 'a)
-> T

? (eq 'david 'a)
-> NIL
you use uppercase or lowercase letters in your symbol names.
Any symbol spelled with a : gets special treatment.
A symbol can name a value. A Lisp symbol most commonly names
a value or -- when used as the first element of a function
call form -- a function.

What's unusual about Lisp is that a symbol can have a value
as a function and a variable at the same time:

? (setq first 'number-one)
-> NUMBER-ONE

? (first (list 3 2 1))
-> 3

? first
-> NUMBER-ONE
When the evaluation rule requires a value, Lisp looks for
the variable value of the symbol. When a function is called for,
Lisp looks for the symbol's function.
A symbol can also have values for its documentation,
property list, and print name.
A value can have more than one name. A value can have more than
one name. That is, more than one symbol can share a value.
Lisp does not expose pointers to the programmer, but does have
shared objects. An object is considered identical when
it passes the EQ test
.

Binding versus Assignment

Lisp often "creates a binding" for a variable by allocating a piece of storage to hold the variable's value and putting the value into the newly allocated memory. Lisp binds function parameters to actual values, but allocates the storage on the stack just like any other programming language. Lisp creates bindings in the heap if it can't determine that the binding has a lifetime which ends when the binding form finishes executing. The SETQ form changes the value of an existing binding.
DEFUN defines named functions. The DEFUN form has three arguments.

Since all three of these should stand for themselves, DEFUN does not evaluate any of its arguments. (If it did, you'd face the inconvenience of having to quote each argument.)

DEFUN returns the name of the defined function, and installs a global definition using the name, parameter list, and body that you supplied. Once you create a function using DEFUN, you can use it right away:

LAMBDA defines anonymous functions. At times you'll need a function in only one place in your program.  Lisp lets you create an unnamed, or anonymous, function using the LAMBDA form. A LAMBDA form looks like a DEFUN form without the name:
(lambda (a b c x)
   (+ (* a (* x x)) (* b x) c))
? ((lambda (a b c x)
(+ (* a (* x x)) (* b x) c))
3 2 7 5)
-> 92


DEFMACRO

(defmacro name (argument ...)
   body)

Macros return a form, not values

? (defmacro setq-literal (place literal)
`(setq ,place ',literal))
-> SETQ-LITERAL

? (setq-literal a b)
-> B
? (defmacro reverse-cons (rest first)
`(cons ,first ,rest))
-> REVERSE-CONS

? (reverse-cons nil A)
-> (B)

If you want to see how your macro body appears before evaluation, you can use the MACROEXPAND function:

? (macroexpand '(setq-literal a b))
-> (SETQ A 'B)

? (macroexpand '(reverse-cons nil a))
-> (CONS A NIL)

Since MACROEXPAND is a function, it evaluates its arguments. This is why you have to quote the form you want expanded.


A form typically returns only one value. Lisp has only a small number of forms which create or receive multiple values.

The VALUES form creates zero or more values:

? (values)

? (values :this)
-> :THIS

? (values :this :that)
-> :THIS
-> :THAT
VALUES is a function, and so evaluates its arguments.


  • bignums are integers with an unlimited number of digits (subject only to limitations
    of computer memory)
  • rational numbers are the exact quotient of two integers, not a floating point number
    resulting from an approximate machine division algorithm
  • Machine integers are called fixnums in Lisp.Lisp will store it as a machine integer.
    But if it gets too big, Lisp automatically promotes it to a bignum.

When I said that Lisp almost always does the right thing with numbers,
I meant that it almost always chooses the numeric representation that is
mathematically correct:

? (/ 1 3)
-> 1/3

? (+ (/ 7 11) (/ 13 31))
-> 360/341

? (defun factorial (n)
(cond ((= n 0) 1)
(t (* n (factorial (- n 1))))))
-> FACTORIAL

? (factorial 100)
-> 933262154439441526816992388562667004907159682643816214685
929638952175999932299156089414639761565182862536979208272
23758251185210916864000000000000000000000000


The READ and WRITE functions turn characters into Lisp objects and
vice versa. READ-CHAR and WRITE-CHAR read and write single characters.
READ
READ collects a symbol, which is terminated by the newline.
? (read)
? aCR
-> A

? (read)
?? #\aCR
-> a
READ-CHAR
In contrast, READ-CHAR reads exactly one character from the input.
? (read-char)
?? a
-> #\a
 WRITE
 WRITE prints the value so that it could be presented to READ to 
create the same value.
? (write 'a)
-> A
=> A

? (write #\a)
=> #\a
-> #\a
WRITE-CHAR
WRITE-CHAR prints just the readable character, without the extra Lisp 
syntax (the #\) that would identify it to READ as a character.
? (write-char #\a)
=> a
-> #\a

? (write-char 'a)
->| Error: Not a character
 

Lisp represents a single character using the notation #\char,
where char is a literal character or the name of a character
that does not have a printable glyph.

Character           Hex Value   Lisp           Standard?
--------------------------------------------------------
  space                 20      #\Space          yes
  newline               --      #\Newline        yes
  backspace             08      #\Backspace      semi
  tab                   09      #\Tab            semi
  linefeed              0A      #\Linefeed       semi
  formfeed              0C      #\Page           semi
  carriage return       0D      #\Return         semi
  rubout or DEL         7F      #\Rubout         semi
 

Only #\Space and #\Newline are required on all Lisp systems.
Systems that use the ASCII character set will probably implement
the rest of the character codes shown above.

The #\Newline character stands for whatever convention represents
the end of a printed line on the host system, e.g.:

System        Newline     Hex Value
-----------------------------------
Macintosh       CR          0D
MS-DOS          CR LF       0D 0A
Unix            LF          0A

The 94 printable standard characters are represented by #\char:

  ! " # $ % & ' ( ) * + , - . / 
0 1 2 3 4 5 6 7 8 9 : ; < = > ? 
@ A B C D E F G H I J K L M N O 
P Q R S T U V W X Y Z [ \ ] ^ _ 
` a b c d e f g h i j k l m n o 
p q r s t u v w x y z { | } ~

 MAKE-ARRAY
Lisp prints an array using the notation #rankA(...). The contents 
of the array appear as nested lists, with the first dimension
appearing as the outermost grouping, and the last dimension
appearing as the elements of the innermost grouping
? (setq a1 (make-array '(3 4)))
-> #2A((NIL NIL NIL NIL)
(NIL NIL NIL NIL)
(NIL NIL NIL NIL))
? (setf (aref a1 0 0) (list 'element 0 0))
-> (ELEMENT 0 0)
AREF
To retrieve an element of an array, use AREF.
 AREF's first argument is the array; the remaining arguments 
specify the index along each dimension. The number of indices
must match the rank of the array.
SETF
SETF is similar to SETQ, except where SETQ assigns a value to 
a symbol, SETF assigns a value to a place. In the examples,
the AREF form specifies the place as an element in the array.
 

Vectors are one-dimensional arrays

? (setq v1 (make-array '(3)))
-> #(NIL NIL NIL)
Lisp prints vectors using the slightly abbreviated form #(...), 
rather than #1A(...).
VECTOR 

You can create a vector from a list of values, using the VECTOR form:

? (vector 34 22 30)
-> #(34 22 30)
ELT

You can use AREF to access the elements of a vector, or you can use
the sequence-specific function, ELT:

? (setf v2 (vector 34 22 30 99 66 77))
-> #(34 22 30 99 66 77)

? (setf (elt v2 3) :radio)
-> :RADIO

? v2
-> #(34 22 30 :RADIO 66 77)

 

Strings are vectors that contain only characters

You already know how to write a string using the "..." syntax.
Since a string is a vector, you can apply the array and vector
functions to access elements of a string.

MAKE-STRING / STRING

? (setq s1 "hello, there.")
-> "hello, there."

? (setf (elt s1 0) #\H))
-> #\H

? (setf (elt s1 1) #\!)
-> #\!

? s1
-> "Hello, there!"

? (string 'a-symbol)
-> "A-SYMBOL"

? (string #\G)
-> "G"
You can also create strings using the MAKE-STRING function 
or change characters or symbols to strings using the STRING function.
 

Symbols are unique, but they have many values