Introduction to lisp

Source: Internet
Author: User

Today, we are far away from the slave table.
-- Zhuge Liang's departure form

LISP is a well-known language with a full name of list processor, the "Table processing language". It was designed by John McCarthy in 1958. Many languages, such as algo, that have emerged even later in the same period as LISP, are now largely extinct, or have minor uses only in some specific scenarios, it is still widely known that only Fortran and COBOL are left. But only lisp, not only does not decline over time, but it is time and time again and again, scheme, ML, and other languages derived from lisp are even more popular in many occasions than many old stars. So what exactly is the secret of the evergreen tree?

If you have only been familiar with C, C ++, and Pascal "procedural languages", LISP may make you feel very unusual, first, attract your attention (or make you feel confused). It must be a lot of parentheses in the lisp program. Of course, from the current perspective, this design is indeed not very friendly to programmers, however, considering the computer processing capabilities of the 50 or 60 s, simplifying the language design was a top priority at that time.

The basic syntax of lisp is very simple, and it does not even have reserved words (some linguistics may disagree with this, Don't be afraid, I'll listen to you). It has only two basic types of data, there is only one basic syntax structure that is the expression, and these expressions are also the program structure, but just as the rule's simplest go has the most complex changes, lisp uses the most basic language structure definition to complete the most complex functions that are difficult to implement in other languages.

Now let's look at the basic elements in the lisp language.

LISPExpressionIsAtom)OrTable (list),Atom is a letter sequence.Such as ABC;A table is a sequence composed of zero or multiple expressions.Between ExpressionsSeparated by spaces and placed in a pair of parenthesesSuch:

ABC
()
(Abc xyz)
(A B (c) d)

The last table is composed of four elements. The third element is also a table.

Just as the arithmetic expression 1 + 1 has a value of 2, the expression in LISP also has a value,If expression e gets the value V, we say E returns v. If an expression is a table, the first element in the table is calledOperatorOther elements are calledIndependent Variable.

Just as there are five theorems in the geometric world of Euclidean, here we will give seven theorems (Basic operators) in the world of LISP ):

  1. (Quote X)Returns X,In short'X
  2. (Atom X)If X is an atomic or empty table, atomic T is returned. Otherwise, an empty table () is returned (). In lisp, we get usedAtomic T is used to represent the truth, while empty table () is used to represent false..
    > (Atom 'a)
    T
    > (Atom '(a B C ))
    ()
    > (Atom '())
    T
    Now we have the first operator to find the value of the independent variable. Let's take a look at the role of the quote operator --By referencing a table, we prevent it from being evaluated.. An unreferenced expression is used as the independent variable. Atom treats it as code, for example:
    > (Atom 'a ))
    T
    On the contrary, a referenced table is only regarded as a table.
    > (Atom '(atom 'a ))
    ()
    Reference seems a bit strange, because it is difficult for you to find similar concepts in other languages, but it is exactly this feature that forms the most distinctive feature of lisp-code and data are represented in the same structure, and we use quote to distinguish them.
  3. (Eq x y) if the values of X and Y are the same or the same as empty tables, t is returned; otherwise, null tables () are returned ()
    > (EQ 'A')
    T
    > (EQ 'A' B)
    ()
    > (EQ '()'())
    T

In the next chapter, we will explain the table-related operators and conditional operators, as well as the basic elements of the lisp Program-functions.

In the previous episode, we talked about the first three of the seven theorems in The LISP world, and we went on to talk about the remaining four.

First, three table operations

  1. (Car X) requires that X is a table, which returns the first element in X.For example,> (car '(a B)
  2. (Cdr x) also requires that X is a table, which returns a table composed of all elements except the first element in X.For example,> (CDR '(a B c) (B C)
  3. (Cons x y) requires y to be a table, which returns a table. The first element of this table is X, followed by all elements in Y.For example,> (cons 'A' (B c) (a B c)> (cons 'a (cons 'B (cons 'C ()))) (a B C)

You may ask why the operator of the element at a position other than the beginning of the table is not used, when we talk about the functions and Recursion that people on earth know, you will know what to do. Maybe you have thought about it now?

Next we will introduce you to a basic function that forms the logic of the program ...... Condition branch. In lisp, it is completed by the cond operator. cond is the last and most complex form of the seven theorems (the last Justice of Euclidean is also true ):

(Cond (P1 E1)(P2 E2)...(Pn En))

P1ToPnAs a condition,E1ToEnAs a result, the cond operator isP1ToPnEvaluate until the first value is found as atomic T (remember ?) OfPIn this caseEReturns the value of the entire expression.For example:

> (Cond (EQ 'a 'B') 'First) (atom 'a) 'Second) Second

Now that we have all the basic principles of the lisp world, we can start to build the rules of the whole world.

Among the seven operators, except quote and cond, expressions starting with the other five operators always need to evaluate all their independent variables and then generate results, we call this expression a function.



 

The king of the world also, the sun of inflammation, the power of God, the letter of the sea, the health of the spring
-- "Chinese book"

In the previous episode, we talked about "functions". In fact, this concept has been learned as early as in junior high school mathematics. A function is nothing more than ing the independent variables to values, the same is true in lisp.

The function definition in lisp is provided in the previous section (quick answer: Who should remember to raise your hand). In lisp, we describe a function in the following form:

(Lambda (P1 P2... PN) e)

Pi is an atomic parameter, which is called a parameter in a function. E is an expression, that is, the function body.

You can call a function as follows:

(Lambda (P1 P2... PN) e) A1 A2...)

Here, AI is an expression, which is called a real parameter according to our practice.

The call process of the entire function is as follows: each expression AI (real parameter) is evaluated first, and then these real parameters are substituted into E for evaluation. The final result is the return value of the entire expression.

If the first element of an expression is an atom, but it is not a basic operator (that is, the seven elements we mentioned earlier), such:

(F A1 A2...)

And the value of F is a function (lambda (P1 P2... PN) E), the above expression is equivalent

(Lambda (P1 P2... PN) e) A1 A2...)

After reading this section, everyone may be a little dizzy. Take a few deep breaths in the window, and then come back to do the following exercises to see what the result of this expression is?

(Lambda (f) (f' (B C) '(lambda (x) (cons 'a X )))

If you get the result, continue reading it. Otherwise, read the previous paragraphs several times and input the exercises to a text editor that can automatically match the brackets.

Here I want to insert a few digress. Many people may have seen this Lambda, but it is unlikely that it is in LISP (if this is the case, you should not look at this "entry", right ?), Most of them are in Python. The Python manual just takes Lambda over. He probably said: "The use of Lambda is because it is similar to a syntax structure with the same name in lisp ." Now let's take a look at the true origins of Lambda's story.

Lambda comes from the lambda algorithm theory. What is Lambda? For people now, this concept is just a "function", but it was a revolutionary innovation in the era when lambda calculus came into being. Lambda calculus is too complicated. As an introduction to lisp, it has completely deviated from the topic, but another concept proposed by Lambda is high order function) -- but it plays an important role in the lisp language. It can be said that it is the main reason why lisp is so distinctive.

Just as "Higher-order derivatives" are "derivative derivatives", the so-called higher-order functions are actually "function functions" (Forgive me, high-number teacher ). That is to say, a function itself is treated as the independent variable of another function (the concept of "functor" proposed in modern c ++ is actually an implementation of high-order functions in C ++ ). The emergence of higher-order functions promotes the role of "functions" in programming languages to a "first-class citizen". You can operate a function just like any basic data type, transform and transmit it as needed.

Next we will go back to the topic and continue to discuss the functions in lisp. We can see that our functions have no names so far, and the functions can have no names, that is, anonymous functions are another feature of Lisp. LISP allows programmers to extract data and names, this is a luxury that many other programming languages have never enjoyed until now.

If a function has no name, it will lead to a problem, that is, you cannot call yourself in the function (well, I know there are y combinations, but this is an introductory article ), therefore, LISP provides a form that allows you to reference a function with an identifier:

(Label F (lambda (P1 P2... PN) e ))

This expression is equivalent to the previous simple Lambda expression, but all F in E will be replaced with the entire Lambda expression, that is, recursion.

At the same time, LISP provides a shorthand form for it:

(Defun F (P1 P2... PN) e)

You can start to write your first useful lisp program. What are you going to write? (Whatever it is, as long as it is not Hello World)

Next, we will provide some common functions.

 

-- Sutra

We have seen the general appearance of a lisp program in the previous episode. At the end of the article, I mentioned that this set will be used to write a lisp interpreter. In fact, this interpreter is not too long, although it may be the longest one you have ever seen so far.

I can't wait. Let's take a look at the entire program and then explain it again:

(Defun eval (e)
(Cond
(Atom E) (assoc e ))
(Atom (car e ))
(Cond
(Eq (car e) 'quote) (cadr e ))
(Eq (car e) 'Atom) (atom (eval (CADR e) )))
(Eq (car e) 'eq) (eq (eval (CADR e))
(Eval (caddr e) )))
(Eq (car e) 'car) (Car (eval (CADR e) )))
(Eq (car e) 'cdr) (CDR (eval (CADR e) )))
(Eq (car e) 'Cons) (Cons (eval (CADR e))
(Eval (caddr e) )))
(Eq (car e) 'cond) (evcon (CDR e) ))
('T (eval (Cons (Assoc (car e))
(Cdr e ))
A ))))
(Eq (caar e) 'label)
(Eval (Cons (caddar E) (cdr e ))
(Cons (List (cadar E) (Car E) )))
(Eq (caar e) 'lambda)
(Eval (caddar E)
(Append (pair (cadar E) (Evlis (CDR e) ))
A )))))

(Defun evcon (c)
(Cond (eval (caar C))
(Eval (cadar C) ))
('T (evcon (cdr c) ))))

(Defun Evlis (m)
(Cond (null m )'())
('T (Cons (eval (CAR m))
(Evlis (CDR m) )))))

(Note: Some readers may have discovered that lisp does not require you to define it before using a function)

The entire program contains three functions. The main function follows the Convention of Lisp (and Python and Perl), called Eval, which is the skeleton of the entire program. The definition of Eval is longer than any previous function, so let's consider how each part of it works.

Eval has two independent variables: E is the expression that requires a value. A is a table composed of values assigned to an atom. These values are somewhat like parameters in function calls. The table in the shape of the returned value of pair is calledContextWe wrote pair and assoc in the previous chapter to construct and search such tables.

The eval skeleton is a cond expression with four clauses. How to evaluate the expression depends on its type. The first branch processes atoms. If E is an atom, we look for its value in the context:

> (eval 'x '((x a) (y b))) a

The second branch is another cond, which processes (A), WhereAIt is an atom. This includes all the basic operators, each corresponding to a branch.

> (eval '(eq 'a 'a) '()) t > (eval '(cons x '(b c)) '((x a) (y b))) (a b c)

These branches (except quote) Call eval to find the value of the independent variable.

The last two branches are more complex. To evaluate the cond expression value, we call an auxiliary function called evcon. It recursively evaluates the cond branch and returns the T clause for the first element. If such a clause is found, it returns the second element of the branch.

> (eval '(cond ((atom x) 'atom) ('t 'list)) '((x '(a b)))) list 

The last part of the second branch processes the function call. It replaces the atom with its value (it should be a Lambda or label expression ). Then evaluate the obtained result expression. So:

(eval '(f '(b c)) '((f (lambda (x) (cons 'a x)))))

Changed:

(eval '((lambda (x) (cons 'a x)) '(b c)) '((f (lambda (x) (cons 'a x)))))

It returns (a B C)

The last two cond branches of eval process the first element is the lambda or label function call. To evaluate the label expression, first press the function name and function itself into the context, and then call eval to evaluate an internal Lambda expression, namely:

(eval '((label firstatom (lambda (x) (cond ((atom x) x) ('t (firstatom (car x)))))) y) '((y ((a b) (c d)))))

Change

(eval '((lambda (x) (cond ((atom x) x) ('t (firstatom (car x))))) y) '((firstatom (label firstatom (lambda (x) (cond ((atom x) x) ('t (firstatom (car x))))))) (y ((a b) (c d)))))

Finally, return.

Finally, (lambda (P1 P2... PN) e) A1 A2... an) expression, call Evlis to obtain the independent variable (A1 A2... an) corresponding value (V1 V2... VN), put (P1 V1) (P2 V2 )... (pn vn) is added to the context, and thenEEvaluate. So:

(eval '((lambda (x y) (cons x (cdr y))) 'a '(b c d)) '())

Changed:

(eval '(cons x (cdr y)) '((x a) (y (b c d))))

Returns (a c d ).

If you have understood the basic programming methods and ideas of Lisp and FP, what can we do with a program that is so long?

Here we get a very elegant computing model. The eval function actually implements the entire language, and we can use it to define any other functions we need. In other words, we now have a lisp of our own.

(Note: it can be seen that the syntax analysis of recursive descent is very good, because it means that you can use dozens or up to 100 or 200 lines of programs to deal with a complex analyzer, compared with lalr, you will be more experienced)

Where should we go next? For this question, please search for the answer yourself.

For thousands of places, it is a perfect combination of troops and a hero industry.
-- Zi Zhi Tong Jian

The syntax elements of Lisp have been basically discussed in the previous few sets. Compared with the specification of hundreds of pages in C # or Java, it may be a little surprising. However, great things are always simple, isn't it? Now let's review the content mentioned in the previous focus. First, let's raise a few questions:

  1. Since cond is equivalent to the IF statement in Procedural language, how should the else branch relative to if be described in the cond expression?
  2. In (what we have learned) lisp, how does one express the semantics of "repetition? Or can you write a foreach loop function?

(Note: Do not ask where the input/output functions or arithmetic logic operations are. They are trivial ......)

In this set, we will describe several common functions and give their simple implementations.

First, I will answer the question raised in the first set: how to obtain the second, third, or nth element in a table?

Some readers may have thought that the second element can take the following form:

(CAR (cdr x ))

Similarly, the third element is like this:

(CAR (cdr x )))

In fact, this combination is often used in lisp. For convenience, LISP provides a general mode-CXR, whereXIt is a sequence of A or D to describe the combination of car and Cdr. For example:

> (Cadr' (a B) (C D) e ))
(C d)
> (Caddr '(a B) (C D) e ))
E
> (Cdar '(a B) (C D) e ))
(B)

In addition, use (list E1 E2... en) to represent
(Cons E1 (cons E2 (... (cons en '())...)))

> (Cons 'a (cons 'B (cons 'C '())))
(A B C)
> (List 'A' B 'C)
(A B C)

Now we define some new common functions. I suggest you think about them first. Don't rush to see the Implementation I have given.

(Note: Some functions already exist in Common LISP, so if you want to test them, change their names)

  1. (Null x) to test whether X is a null table. For example:
    > (Null 'a)
    ()
    > (Null '())
    T
  2. (And x y), logic and. if and only if both X and Y are not empty tables, return 'T'; otherwise, return empty tables.
    > (And 'A' B)
    T
    > (And (atom 'a) (EQ 'B' C ))
    ()
  3. (Not X). The logic is not. If X is an empty table,'t is returned. Otherwise, an empty table is returned. (Someone asked me where I am or ?) For example:
    > (Not 'a)
    ()
    > (Not (EQ 'A' B ))
    T
  4. (Append x y) connects two tables X and Y. Note the differences between them and cons and list. For example:
    > (Append '(a B)' (C D ))
    (A B C D)
    > (Append? '()' (X y ))
    (X y)
  5. (Pair x y). Here, X and Y are two tables of the same length. Pair generates a table, each element is an element pair composed of elements at the corresponding positions in X and Y. the return value of this function is similar to the concept of map or dictionary in other languages. For example:
    > (Pair '(a B C)' (x y z ))
    (A X) (B y) (C z ))
  6. (Assoc x y) where X is an atom and Y is a table in the shape of pair returned. Assoc searches for the first element pair whose left element is X in Y and returns it. For example:
    > (Assoc 'A' (a X) (B y )))
    X
    > (Assoc 'A' (A (FOO bar) (B y) (C z )))
    (FOO bar)
  7. (Subst x y z). In table Z, replace atomic y at any level with expression X. For example:
    > (SUBST '(x y)' B '(a B C) D ))
    (A (x Y) (a (x Y) c) d)

The following describes the simple implementation of these common functions:

  1. (Defun null (X)
    (EQ x '()))
  2. (Defun and (x Y)
    (Cond (x (cond (y't) ('T '())))
    ('T '())))
  3. (Defun not (X)
    (Cond (x '())
    ('T )))
  4. (Defun append (x y)
    (Cond (Null x) y)
    ('T (Cons (car x) (append (CDR x) y )))))
  5. (Defun pair (x y)
    (Cond (and (Null x) (null y ))'())
    (And (not (atom X) (not (atom y )))
    (Cons (List (car x) (Car y ))
    (Pair (CDR) (CDR y ))))))
  6. (Defun Assoc (x y)
    (Cond (eq (caar y) X) (cadar y ))
    ('T (assoc X (CDR y )))))
  7. (Defun SUBST (x y z)
    (Cond (atom Z)
    (Cond (eq z y) X)
    ('T z )))
    ('T (Cons (subst x y (CAR z ))
    (Subst x y (CDR z ))))))

If you see that you are not dizzy, it means that your nerves are really strong. Note how to express the concept of "repetition" in these examples. In lisp, the most common repetition is actually not actually a true repetition, but recursion, this is also a common feature of the vast majority of Functional Languages-nested and recursive functions constitute the entire program logic.

This part of content makes you really feel the characteristics of Lisp. Compared with programming in procedural languages, writing Lisp programs requires a completely different way of thinking, maybe this is the real reason why the lisp language has been booming for decades.

After understanding this part, we will teach you the power of Lisp in the next episode. We will use LISP to write a lisp interpreter. If you have never seen this program before, I promise it will surprise you.

 

(From csdn)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.