Why is Lisp still advanced?

Source: Internet
Author: User
If we sort popular programming languages in this order: Java, Perl, Python, and Ruby. You will find that the language that comes behind is more like Lisp. Python imitates Lisp, and even imitates what many Lisp hackers think is a wrong design function. As for Ruby, if you go back to 1975, you claim that it is a Lisp dialect, and no one will oppose it. The development of the programming language is just one

If we sort popular programming languages in this order: Java, Perl, Python, and Ruby. You will find that the language that comes behind is more like Lisp.

Python imitates Lisp, and even imitates what many Lisp hackers think is a wrong design function. As for Ruby, if you go back to 1975, you claim that it is a Lisp dialect, and no one will oppose it.

The current development of programming languages has just caught up with the level of Lisp in 1958.

II

In 1958, John McCarthy designed the Lisp language. In my opinion, the latest programming language just realized his vision in 1958.

How is this possible? Isn't the development of computer technology ever changing? How can the technology in 1958 surpass today's level?

Let me tell you why.

This is because John McCarthy was not planning to design Lisp into a programming language, at least not in our current sense. His original intention was to make a theoretical calculation and define the Turing machine in a more concise way.

So why is the programming language of the 1950s s not outdated yet? Simply put, this language is essentially not a technology, but a mathematics. Mathematics is not outdated. Rather than associating the Lisp language with the hardware in 1950s, you should compare it with the Quicksort algorithm. This algorithm was proposed in 1960 and is still the fastest general sorting method.

3.

The Fortran language emerged in the 1950s s and has been used since now. It represents a completely different direction of language design. Lisp was inadvertently developed from pure theory to programming language, while Fortran was designed as a programming language from the very beginning. However, today we regard Lisp as a high-level language, while Fortran as a rather low-level language.

In 1956, when Fortran was born, it was called Fortran I, which is very different from today's Fortran language. Fortran I is actually an assembly language plus Mathematics. in some aspects, it is not as powerful as today's assembly language. For example, it does not support subprograms, but only the branch jump structure (branch ).

Lisp and Fortran represent the development of programming languages. The former is based on mathematics, and the latter is based on hardware architecture. Since then, the two directions have been moving closer to each other. When Lisp was designed, it was very powerful. in the next two decades, it improved its running speed. The so-called mainstream languages use faster running speed as the starting point of design, and then use more than 40 years to become more powerful step by step.

Today, the most advanced mainstream language is just close to the level of Lisp. Although it is very close, it is still not as powerful as Lisp.

Thu

When the Lisp language was born, it contained nine new ideas. Some of them are used to today, while others have just appeared in other advanced languages. so far, there are two other types that are unique to Lisp. According to the degree of public acceptance, these nine ideas are:

  1. Condition structure (that is, the "if-then-else" structure ). Now everyone thinks this is taken for granted, but Fortran I does not have this structure. it only has a goto structure based on the underlying machine commands.
  2. A function is also a data type. In Lisp, functions, like integers or strings, are also data types. It has its own literal representation, which can be stored in variables and passed as parameters. All functions of a data type are available.
  3. Recursion. Lisp is the first advanced language that supports recursive functions.
  4. The dynamic type of the variable. In the Lisp language, all variables are actually pointers, and the values are of different types, but the variables themselves do not. Copying variables is equivalent to copying pointers, rather than copying the data they point.
  5. Garbage collection mechanism.
  6. A program consists of expressions. A Lisp program is a set of expression blocks. each expression returns a value. This is completely different from Fortran and most later languages. their programs are composed of expressions and statements (statement.
  7. Distinguishing expressions and statements is natural in Fortran I, because it does not support nested statements. Therefore, if you need to use a mathematical formula to calculate a value, only this value is returned using an expression. No other syntax structure is available, because otherwise the value cannot be processed.

    Later, the new programming language supported block structures, which of course did not exist. However, it is too late, and the distinction between expressions and statements is deep-rooted. It spreads from Fortran To The Algol language, and then to the successor languages of the two.

  8. Symbol type. A symbol is actually a pointer pointing to a string stored in a hash table. Therefore, to compare whether two symbols are equal, you only need to check whether their pointers are the same. you do not need to compare them one by one.
  9. The code uses a tree representation (notation) composed of symbols and constants ).
  10. The entire language is available at any time. Lisp does not really distinguish between the read period, compilation period, and runtime period. You can compile or run the code during the read period, read or run the code during the compilation period, and read or compile the code during the runtime.

Run the code during the read period so that you can re-adjust the (reprogram) Lisp syntax. running the code during the compilation period is the basis of the work of the Lisp macro; compiling the code during the runtime, this allows Lisp to act as an extension language in programs such as Emacs. it reads code at runtime so that programs can communicate with each other using the S-expression, the emergence of XML format has recently led to the re-"invention" of this concept.

V.

When the Lisp language emerged, its idea was quite different from that of other programming languages. The latter's design philosophy is mainly determined by the hardware in the later 1950s s. As time passes, popular programming languages are constantly updated, and language design ideas are gradually moving closer to Lisp.

Ideology 1 to ideology 5 has been widely accepted. ideology 6 has already appeared in mainstream programming languages. idea 7 has been implemented in Python, but it does not seem to have a dedicated syntax.

Thought 8 may be the most interesting. It and idea 9 become part of the Lisp language only by chance, because they are not part of John McCarthy's original ideas and are added by his student Steve Russell. These made Lisp seem odd, but also became the most unique feature of this language. The odd form of Lisp is not because its syntax is odd, but because it has no syntax at all, and the program is expressed directly in the form of a parse tree. In other languages, this form is generated only after parsing in the background, but Lisp uses it as the expression form directly. It consists of the list, and the list is the basic data structure of Lisp.

Using a language's own data structure to express the language proves to be very powerful. Thought 8 and thought 9 mean that you can write a program that can be programmed by yourself. This may sound weird, but it is not common for Lisp. The most common practice is to use macros.

The term "macro" in Lisp is different from that in other languages. Lisp macros are all-encompassing. they may be a scaling form of a certain expression or a compiler in a new language. If you want to really understand the Lisp language or broaden your programming horizons, you must learn macros.

As far as I know, macros (defined in the Lisp language) are still unique to Lisp. One reason is that to use macros, you probably have to make your language look as weird as Lisp. Another possible reason is that if you want to add this NLP weapon to your language, you cannot claim that you have invented a new language, but you can only say that you have invented a new dialect of Lisp.

I told it as a joke, but this is the case. If you create a new language with functions such as car, cdr, cons, quote, cond, atom, and eq, you can also write functions as a list representation, then, based on these, you can completely export all the other parts of the Lisp language. In fact, the Lisp language is defined in this way. John McCarthy designed the language to make this derivation possible.

Sat.

Even if Lisp really represents the current direction that mainstream programming languages are constantly approaching, does that mean you should use it to program?

If you use a language that is less powerful, how much do you suffer? Isn't it a wise choice to choose from the most advanced technology? If so many people use mainstream programming languages, doesn't that show their merits?

On the other hand, it doesn't matter which programming language you choose. many projects can be completed in different languages. In general, the more demanding the project, the more powerful programming languages can play a role. However, numerous projects do not have strict restrictions. Most programming tasks may only need to write small programs and then use the glue language to connect these small programs. You can use programming languages you are familiar with, or use languages with the most powerful function libraries for specific projects to write these applets. If you only need to transmit data between Windows applications, Visual Basic can achieve the same purpose.

So what are the advantages of Lisp programming?

VII.

The more powerful the programming capability of a language, the shorter the program to be written (not the number of characters, but an independent syntax unit ).

The number of codes is very important, because the time required to develop a program depends mainly on the length of the program. If the code written in one language is three times longer than the code written in another language, it means that it takes three times more time to develop it. And even if you hire more people, it will not help reduce development time, because when the team size exceeds a certain threshold, increasing the number of people will only cause a net loss. Fred Brooks described this phenomenon in his famous book "The Mythical Man-Month". what I have seen proves his theory.

How short can a program be in the Lisp language? Taking the comparison between Lisp and C as an example, most of the statements I have heard are that C code is 7 to 10 times the length of Lisp. But recently, there was an article about the ITA software company in the magazine "a line of Lisp code is equivalent to 20 lines of C code", because this article references the President of ITA, so I think this number comes from the programming practices of ITA. If so, we can believe this sentence. The ITA software not only uses the Lisp language, but also uses C and C ++ in large quantities at the same time, so this is their experience.

Based on the figure above, if you compete with ITA and you develop software using C language, the development speed of ITA will be 20 times faster than that of you. If you need to implement a function within one year, it only takes less than three weeks. Conversely, if a new feature has been developed for three months, it takes five years to complete.

Do you know? The comparison above only takes into account the best situation. When we only compare the number of codes, the implication is that we can develop the same software if we use a language with weak functionality. But in fact, there is a limit to what programmers can do in a certain language. If you want to use a low-level language to solve a difficult problem, you will be faced with a situation that is extremely complicated or even unclear.

So when I say that if you are competing with ITA and you have made something in five years, it takes only three months for ITA to complete it with the help of the Lisp language, in the five years that I have been talking about, everything went well, there were no mistakes, and there were no major troubles. In fact, according to the actual situation of most companies, projects planned to be completed within five years may never be completed.

I admit, the above example is Taiji. ITA seems to have a group of very smart hackers, and C language is a very low-level language. However, in a highly competitive market, even if the development speed is only two or three times different, it is enough to keep you behind.

Appendix: programming capability

To explain the differences in programming capabilities, consider the following questions. We need to write a function that can generate the accumulators. that is, this function accepts the n parameter and returns the other function. The latter accepts the I parameter and then returns the n increment (increment) the value after I.

Common Lisp is written as follows:

  (defun foo (n)    (lambda (i) (incf n i)))

Ruby is written almost identical:

  def foo (n)    lambda {|i| n += i } end

The write rules for Perl 5 are:

  sub foo {    my ($n) = @_;    sub {$n += shift}  }

This has more syntax elements than Lisp and Ruby versions, because in Perl, you have to extract parameters manually.

The syntax of Smalltalk is a little longer than that of Lisp and Ruby:

  foo: n    |s|    s := n.    ^[:i| s := s+i. ]

In Smalltalk, the local variable (lexical variable) is valid, but you cannot assign values to a parameter. Therefore, you have to set a new variable to accept the accumulated value.

The Javascript syntax is a little longer than that of Lisp and Ruby. Because Javascript still distinguishes between statements and expressions, you need to specify the return statement to return a value:

  function foo (n) {    return function (i) {      return n += i } }

Practically speaking, Perl also retains the differences between statements and expressions, but uses a typical Perl method for processing, so that you can omit return.

If you want to change the version of Lisp/Ruby/Perl/Smalltalk/Javascript to Python, you will encounter some restrictions. Because Python does not fully support local variables, you have to create a data structure to accept n values. And although Python does support function data, there is no literal representation (literal representation) that can generate a function (unless the function body has only one expression ), so you need to create a name function and return it. The final statement is as follows:

  def foo (n):    s = [n]    def bar (i):      s[0] += i      return s[0]    return bar

Python users can reasonably question why it cannot be written as follows:

  def foo (n):    return lambda i: return n += i

Or:

  def foo (n):    lambda i: n += i

I guess Python will support this method one day. (If you don't want to wait until Python gradually evolves to be more like Lisp, you can always directly ......)

In an object-oriented programming language, you can simulate a closure to a limited extent (that is, a function that can reference the variables defined by the code containing this function ). You define a class with a method and an attribute to replace all variables in the closed scope. This is similar to letting programmers perform code analysis on their own. Originally, this should be done by a compiler that supports local scopes. If there are multiple functions pointing to the same variable at the same time, this method will become invalid, but in this simple example, it is enough.

Python experts also agreed that this is a good solution to this problem, written as follows:

  def foo (n):    class acc:      def _ _init_ _ (self, s):        self.s = s      def inc (self, i):        self.s += i        return self.s    return acc (n).inc

Or

  class foo:    def _ _init_ _ (self, n):      self.n = n    def _ _call_ _ (self, i):      self.n += i      return self.n

I added this section because I want to avoid a Python enthusiast saying that I misunderstand this language. However, in my opinion, these two methods seem to be more complex than the first version. You are actually doing the same thing, but you just draw an independent region and save the accumulators function. The difference is that the function is saved in an attribute of the object rather than in the list). Using these special internal attribute names (especially _ call _) does not look like a common solution, but more like a cracking.

In the contest between Perl and Python, Python hackers seem to think that Python is more elegant than Perl, but this example shows that programming capabilities ultimately determine elegance. Perl is easier to write (with fewer syntax elements), although its syntax is a bit ugly.

How about other languages? As mentioned above, Fortran, C, C ++, Java, and Visual Basic cannot be used. Ken Anderson said that Java can only write an approximate solution:

  public interface Inttoint {    public int call (int i);  }  public static Inttoint foo (final int n) {    return new Inttoint () {    int s = n;    public int call (int i) {    s = s + i;    return s;    }};  }

This method does not meet the question requirements, because it is only valid for integers.

Of course, I said that using other languages cannot solve this problem. This sentence is not completely correct. All of these languages are Turing equivalent, which means strictly speaking that you can use any of them to write any program. So how can we achieve this? In this small example, you can use these less powerful languages to write a Lisp interpreter.

This may sound like a joke, but it is widely used in large programming projects to varying degrees. Therefore, some people name it Greenspun's Tenth Rule ):

"After any C or Fortran program is complex to a certain extent, it will contain a Common Lisp implementation that is temporarily developed, with only half of the functions, not fully compliant with specifications, bug everywhere, and slow running. "

If you want to solve a difficult problem, the key is not whether the language you are using is powerful, but that several factors play a role at the same time:

  1. Use a powerful language.
  2. Write a real interpreter for this problem.
  3. You turn yourself into a human-handed compiler for this problem.

In the Python example, this processing method has started to appear. we actually write our own code to simulate the compiler's function of implementing local variables.

This practice is not only common, but also systematic. For example, in the world of object-oriented programming, we hear the word pattern in many ways, and I think those patterns are actually factors (c ), that is, the human flesh compiler. When I found the pattern in my own program, I thought it would indicate that something went wrong. The program form should only reflect the problems it wants to solve. Any other form of addition in the code is a signal (at least for me) indicating that I am not abstract enough to the problem, and often remind me of what I am doing manually, code should be written and automatically implemented through macro extension.

This article is available at http://www.nowamagic.net/librarys/veda/detail/201.

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.