-
2
-
-
84891984524
-
-
Unfortunately, there's little actual research on the productivity of different languages. One report that shows Lisp coming out well compared to C++ and Java in the combination of programmer and program efficiency is discussed at
-
Unfortunately, there's little actual research on the productivity of different languages. One report that shows Lisp coming out well compared to C++ and Java in the combination of programmer and program efficiency is discussed at http://www.norvig.com/java-lisp. html.
-
-
-
-
3
-
-
84957769662
-
-
Peopleware: Productive Projects and Teams by Tom De Marco and Timothy Lister Dorset House, 1987. The two key facts about flow are that it takes around 15 minutes to get into a state of flow and that even brief interruptions can break you right out of it, requiring another 15-minute immersion to reenter. De Marco and Lister, like most subsequent authors, concerned themselves mostly with flow-destroying interruptions such as ringing telephones and inopportune visits from the boss. Less frequently considered but probably just as important to programmers are the interruptions caused by our tools. Languages that require, for instance, a lengthy compilation before you can try your latest code can be just as inimical to flow as a noisy phone or a nosy boss. So, one way to look at Lisp is as a language designed to keep you in a state of flow
-
Psychologists have identified a state of mind called flow in which we're capable of incredible concentration and productivity. The importance of flow to programming has been recognized for nearly two decades since it was discussed in the classic book about human factors in programming Peopleware: Productive Projects and Teams by Tom De Marco and Timothy Lister (Dorset House, 1987). The two key facts about flow are that it takes around 15 minutes to get into a state of flow and that even brief interruptions can break you right out of it, requiring another 15-minute immersion to reenter. De Marco and Lister, like most subsequent authors, concerned themselves mostly with flow-destroying interruptions such as ringing telephones and inopportune visits from the boss. Less frequently considered but probably just as important to programmers are the interruptions caused by our tools. Languages that require, for instance, a lengthy compilation before you can try your latest code can be just as inimical to flow as a noisy phone or a nosy boss. So, one way to look at Lisp is as a language designed to keep you in a state of flow.
-
-
-
-
4
-
-
84957747658
-
-
This point is bound to be somewhat controversial, at least with some folks. Static versus dynamic typing is one of the classic religious wars in programming. If you're coming from C++ and Java or from statically typed functional languages such as Haskel and ML and refuse to consider living without static type checks, you might as well put this book down now. However, before you do, you might first want to check out what self-described "statically typed bigot" Robert Martin author of Designing Object Oriented C++ Applications Using the Booch Method Prentice Hall, 1995 and C++ and Java author Bruce Eckel author of Thinking in C++ Prentice Hall, 1995 and Thinking in Java Prentice Hall, 1998 have had to say about dynamic typing on their weblogs, and http://www.mindview.net/WebLog/log-0025, On the other hand, folks coming from Smalltalk, Python, Perl, or Ruby should feel right at home with this aspect of Common Lisp
-
This point is bound to be somewhat controversial, at least with some folks. Static versus dynamic typing is one of the classic religious wars in programming. If you're coming from C++ and Java (or from statically typed functional languages such as Haskel and ML) and refuse to consider living without static type checks, you might as well put this book down now. However, before you do, you might first want to check out what self-described "statically typed bigot" Robert Martin (author of Designing Object Oriented C++ Applications Using the Booch Method [Prentice Hall, 1995]) and C++ and Java author Bruce Eckel (author of Thinking in C++ [Prentice Hall, 1995] and Thinking in Java [Prentice Hall, 1998]) have had to say about dynamic typing on their weblogs (http://www.artima.com/weblogs/viewpost.jsp?thread=4639 and http://www.mindview.net/WebLog/log-0025). On the other hand, folks coming from Smalltalk, Python, Perl, or Ruby should feel right at home with this aspect of Common Lisp.
-
-
-
-
5
-
-
84892002221
-
-
AspectL is an interesting project insofar as AspectJ, its Java-based predecessor, was written by Gregor Kiczales, one of the designers of Common Lisp's object and metaobject systems. To many Lispers, AspectJ seems like Kiczales's attempt to backport his ideas from Common Lisp into Java. However, Pascal Costanza, the author of AspectL, thinks there are interesting ideas in AOP that could be useful in Common Lisp. Of course, the reason he's able to implement AspectL as a library is because of the incredible flexibility of the Common Lisp Meta Object Protocol Kiczales designed. To implement AspectJ, Kiczales had to write what was essentially a separate compiler that compiles a new language into Java source code. The AspectL project page is at http://common-lisp. net/project/aspectl/.
-
-
-
-
6
-
-
84891984640
-
-
Or to look at it another, more technically accurate, way, Common Lisp comes with a built-in facility for integrating compilers for embedded languages
-
Or to look at it another, more technically accurate, way, Common Lisp comes with a built-in facility for integrating compilers for embedded languages.
-
-
-
-
8
-
-
84891999853
-
-
Ideas first introduced in Lisp include the if/then/else construct, recursive function calls, dynamic memory allocation, garbage collection, first-class functions, lexical closures, interactive programming, incremental compilation, and dynamic typing
-
Ideas first introduced in Lisp include the if/then/else construct, recursive function calls, dynamic memory allocation, garbage collection, first-class functions, lexical closures, interactive programming, incremental compilation, and dynamic typing.
-
-
-
-
10
-
-
84892094470
-
-
The first two Lisp Machine Emacs, following the hacker tradition of recursive acronyms, were EINE and ZWEI, which stood for EINE Is Not Emacs and ZWEI Was EINE Initially. Later ones used a descendant of ZWEI, named, more prosaically, ZMACS
-
If you've had a bad experience with Emacs previously, you should treat Lisp in a Box as an IDE that happens to use an Emacs-like editor as its text editor; there will be no need to become an Emacs guru to program Lisp. It is, however, orders of magnitude more enjoyable to program Lisp with an editor that has some basic Lisp awareness. At a minimum, you'll want an editor that can automatically match () s for you and knows how to automatically indent Lisp code. Because Emacs is itself largely written in a Lisp dialect, Elisp, it has quite a bit of support for editing Lisp code. Emacs is also deeply embedded into the history of Lisp and the culture of Lisp hackers: the original Emacs and its immediate predecessors, TECMACS and TMACS, were written by Lispers at the Massachusetts Institute of Technology (MIT). The editors on the Lisp Machines were versions of Emacs written entirely in Lisp. The first two Lisp Machine Emacs, following the hacker tradition of recursive acronyms, were EINE and ZWEI, which stood for EINE Is Not Emacs and ZWEI Was EINE Initially. Later ones used a descendant of ZWEI, named, more prosaically, ZMACS.
-
-
-
-
11
-
-
84957786811
-
-
Practically speaking, there's very little likelihood of the language standard itself being revised-while there are a small handful of warts that folks might like to clean up, the ANSI process isn't amenable to opening an existing standard for minor tweaks, and none of the warts that might be cleaned up actually cause anyone any serious difficulty. The future of Common Lisp standardization is likely to proceed via de facto standards, much like the "standardization" of Perl and Python-as different implementers experiment with application programming interfaces APIs and libraries for doing things not specified in the language standard, other implementers may adopt them or people will develop portability libraries to smooth over the differences between implementations for features not specified in the language standard
-
Practically speaking, there's very little likelihood of the language standard itself being revised-while there are a small handful of warts that folks might like to clean up, the ANSI process isn't amenable to opening an existing standard for minor tweaks, and none of the warts that might be cleaned up actually cause anyone any serious difficulty. The future of Common Lisp standardization is likely to proceed via de facto standards, much like the "standardization" of Perl and Python-as different implementers experiment with application programming interfaces (APIs) and libraries for doing things not specified in the language standard, other implementers may adopt them or people will develop portability libraries to smooth over the differences between implementations for features not specified in the language standard.
-
-
-
-
14
-
-
84892102236
-
-
SBCL forked from CMUCL in order to focus on cleaning up the internals and making it easier to maintain. But the fork has been amiable; bug fixes tend to propagate between the two projects, and there's talk that someday they will merge back together
-
SBCL forked from CMUCL in order to focus on cleaning up the internals and making it easier to maintain. But the fork has been amiable; bug fixes tend to propagate between the two projects, and there's talk that someday they will merge back together.
-
-
-
-
15
-
-
84892051281
-
-
The venerable "hello, world" predates even the classic Kernighan and Ritchie C book that played a big role in its popularization. The original "hello, world" seems to have come from Brian Kernighan's "A Tutorial Introduction to the Language B" that was part of the Bell Laboratories Computing Science Technical Report #8: The Programming Language B published in January 1973. (It's available online at http://cm.bell-labs.com/cm/ cs/who/dmr/bintro.html.)
-
-
-
-
16
-
-
84892028740
-
-
These are some other expressions that also print the string "hello, world": write-line "hello, world" or this: print "hello, world"
-
These are some other expressions that also print the string "hello, world": (write-line "hello, world") or this: (print "hello, world")
-
-
-
-
17
-
-
84891968300
-
-
Well, as you'll see when I discuss returning multiple values, it's technically possible to write expressions that evaluate to no value, but even such expressions are treated as returning NIL when evaluated in a context that expects a value
-
Well, as you'll see when I discuss returning multiple values, it's technically possible to write expressions that evaluate to no value, but even such expressions are treated as returning NIL when evaluated in a context that expects a value.
-
-
-
-
18
-
-
84892046283
-
-
I'll discuss in Chapter 4 why the name has been converted to all uppercase
-
I'll discuss in Chapter 4 why the name has been converted to all uppercase.
-
-
-
-
19
-
-
84892137871
-
-
You could also have entered the definition as two lines at the REPL, as the REPL reads whole expressions, not lines
-
You could also have entered the definition as two lines at the REPL, as the REPL reads whole expressions, not lines.
-
-
-
-
20
-
-
84892139336
-
-
SLIME shortcuts aren't part of Common Lisp-they're commands to SLIME
-
SLIME shortcuts aren't part of Common Lisp-they're commands to SLIME.
-
-
-
-
21
-
-
84957739847
-
-
If for some reason the LOAD doesn't go cleanly, you'll get another error and drop back into the debugger. If this happens, the most likely reason is that Lisp can't find the file, probably because its idea of the current working directory isn't the same as where the file is located. In that case, you can quit the debugger by typing q and then use the SLIME shortcut cd to change Lisp's idea of the current directory-type a comma and then cd when prompted for a command and then the name of the directory where hello.lisp was saved
-
If for some reason the LOAD doesn't go cleanly, you'll get another error and drop back into the debugger. If this happens, the most likely reason is that Lisp can't find the file, probably because its idea of the current working directory isn't the same as where the file is located. In that case, you can quit the debugger by typing q and then use the SLIME shortcut cd to change Lisp's idea of the current directory-type a comma and then cd when prompted for a command and then the name of the directory where hello.lisp was saved.
-
-
-
-
22
-
-
84892123122
-
-
http://www.flownet.com/gat/jpl-lisp. html
-
-
-
-
23
-
-
84892136298
-
-
Before I proceed, however, it's crucially important that you forget anything you may know about #define-style "macros" as implemented in the C pre-processor. Lisp macros are a totally different beast
-
Before I proceed, however, it's crucially important that you forget anything you may know about #define-style "macros" as implemented in the C pre-processor. Lisp macros are a totally different beast.
-
-
-
-
24
-
-
84957782909
-
-
One of the coolest FORMAT directives is the-R directive. Ever want to know how to say a really big number in English words? Lisp knows. Evaluate this: format nil "-r" 1606938044258990275541962092 and you should get back the following wrapped for legibility: one octillion six hundred six septillion nine hundred thirty-eight sextillion forty-four quintillion two hundred fifty-eight quadrillion nine hundred ninety trillion two hundred seventy-five billion five hundred forty-one million nine hundred sixty-two thousand ninety-two
-
One of the coolest FORMAT directives is the-R directive. Ever want to know how to say a really big number in English words? Lisp knows. Evaluate this: (format nil "-r" 1606938044258990275541962092) and you should get back the following (wrapped for legibility): one octillion six hundred six septillion nine hundred thirty-eight sextillion forty-four quintillion two hundred fifty-eight quadrillion nine hundred ninety trillion two hundred seventy-five billion five hundred forty-one million nine hundred sixty-two thousand ninety-two
-
-
-
-
25
-
-
84892062741
-
-
Windows actually understands forward slashes in filenames even though it normally uses a backslash as the directory separator. This is convenient since otherwise you have to write double backslashes because backslash is the escape character in Lisp strings
-
Windows actually understands forward slashes in filenames even though it normally uses a backslash as the directory separator. This is convenient since otherwise you have to write double backslashes because backslash is the escape character in Lisp strings.
-
-
-
-
26
-
-
84892023465
-
-
The word lambda is used in Lisp because of an early connection to the lambda calculus, a mathematical formalism invented for studying mathematical functions
-
The word lambda is used in Lisp because of an early connection to the lambda calculus, a mathematical formalism invented for studying mathematical functions.
-
-
-
-
27
-
-
84891997008
-
-
The technical term for a function that references a variable in its enclosing scope is a closure because the function "closes over" the variable. I'll discuss closures in more detail in Chapter 6
-
The technical term for a function that references a variable in its enclosing scope is a closure because the function "closes over" the variable. I'll discuss closures in more detail in Chapter 6.
-
-
-
-
28
-
-
84957781285
-
-
You need to use the name delete-rows rather than the more obvious delete because there's already a function in Common Lisp called DELETE. The Lisp package system gives you a way to deal with such naming conflicts, so you could have a function named delete if you wanted. But I'm not ready to explain packages just yet
-
You need to use the name delete-rows rather than the more obvious delete because there's already a function in Common Lisp called DELETE. The Lisp package system gives you a way to deal with such naming conflicts, so you could have a function named delete if you wanted. But I'm not ready to explain packages just yet.
-
-
-
-
29
-
-
84957785623
-
-
If you're worried that this code creates a memory leak, rest assured: Lisp was the language that invented garbage collection and heap allocation for that matter. The memory used by the old value of db will be automatically reclaimed, assuming no one else is holding on to a reference to it, which none of this code is
-
If you're worried that this code creates a memory leak, rest assured: Lisp was the language that invented garbage collection (and heap allocation for that matter). The memory used by the old value of db will be automatically reclaimed, assuming no one else is holding on to a reference to it, which none of this code is.
-
-
-
-
30
-
-
84957766696
-
-
A friend of mine was once interviewing an engineer for a programming job and asked him a typical interview question: how do you know when a function or method is too big? Well, said the candidate, I don't like any method to be bigger than my head. You mean you can't keep all the details in your head? No, I mean I put my head up against my monitor, and the code shouldn't be bigger than my head
-
A friend of mine was once interviewing an engineer for a programming job and asked him a typical interview question: how do you know when a function or method is too big? Well, said the candidate, I don't like any method to be bigger than my head. You mean you can't keep all the details in your head? No, I mean I put my head up against my monitor, and the code shouldn't be bigger than my head.
-
-
-
-
31
-
-
84957768905
-
-
It's unlikely that the cost of checking whether keyword parameters had been passed would be a detectible drag on performance since checking whether a variable is NIL is going to be pretty cheap. On the other hand, these functions returned by where are going to be right in the middle of the inner loop of any select, update, or delete-rows call, as they have to be called once per entry in the database. Anyway, for illustrative purposes, this will have to do
-
It's unlikely that the cost of checking whether keyword parameters had been passed would be a detectible drag on performance since checking whether a variable is NIL is going to be pretty cheap. On the other hand, these functions returned by where are going to be right in the middle of the inner loop of any select, update, or delete-rows call, as they have to be called once per entry in the database. Anyway, for illustrative purposes, this will have to do.
-
-
-
-
32
-
-
84892122876
-
-
Macros are also run by the interpreter-however, it's easier to understand the point of macros when you think about compiled code. As with everything else in this chapter, I'll cover this in greater detail in future chapters
-
Macros are also run by the interpreter-however, it's easier to understand the point of macros when you think about compiled code. As with everything else in this chapter, I'll cover this in greater detail in future chapters.
-
-
-
-
33
-
-
84892047072
-
-
http://www-formal.stanford.edu/jmc/history/lisp/node3.html
-
-
-
-
34
-
-
84957778423
-
-
Lisp implementers, like implementers of any language, have many ways they can implement an evaluator, ranging from a "pure" interpreter that interprets the objects given to the evaluator directly to a compiler that translates the objects into machine code that it then runs. In the middle are implementations that compile the input into an intermediate form such as bytecodes for a virtual machine and then interprets the bytecodes. Most Common Lisp implementations these days use some form of compilation even when evaluating code at run time
-
Lisp implementers, like implementers of any language, have many ways they can implement an evaluator, ranging from a "pure" interpreter that interprets the objects given to the evaluator directly to a compiler that translates the objects into machine code that it then runs. In the middle are implementations that compile the input into an intermediate form such as bytecodes for a virtual machine and then interprets the bytecodes. Most Common Lisp implementations these days use some form of compilation even when evaluating code at run time.
-
-
-
-
35
-
-
84892055782
-
-
Sometimes the phrase s-expression refers to the textual representation and sometimes to the objects that result from reading the textual representation. Usually either it's clear from context which is meant or the distinction isn't that important
-
Sometimes the phrase s-expression refers to the textual representation and sometimes to the objects that result from reading the textual representation. Usually either it's clear from context which is meant or the distinction isn't that important.
-
-
-
-
36
-
-
84892138973
-
-
Not all Lisp objects can be written out in a way that can be read back in. But anything you can READ can be printed back out "readably" with PRINT
-
Not all Lisp objects can be written out in a way that can be read back in. But anything you can READ can be printed back out "readably" with PRINT.
-
-
-
-
37
-
-
84892058254
-
-
The empty list, which can also be written NIL, is both an atom and a list
-
The empty list, (), which can also be written NIL, is both an atom and a list.
-
-
-
-
38
-
-
84892088616
-
-
The case-converting behavior of the reader can, in fact, be customized, but understanding when and how to change it requires a much deeper discussion of the relation between names, symbols, and other program elements than I'm ready to get into just yet
-
The case-converting behavior of the reader can, in fact, be customized, but understanding when and how to change it requires a much deeper discussion of the relation between names, symbols, and other program elements than I'm ready to get into just yet.
-
-
-
-
39
-
-
84892008263
-
-
I'll discuss the relation between symbols and packages in more detail in Chapter 21
-
I'll discuss the relation between symbols and packages in more detail in Chapter 21.
-
-
-
-
40
-
-
84892069127
-
-
Of course, other levels of correctness exist in Lisp, as in other languages. For instance, the s-expression that results from reading foo 1 2 is syntactically well-formed but can be evaluated only if foo is the name of a function or macro
-
Of course, other levels of correctness exist in Lisp, as in other languages. For instance, the s-expression that results from reading (foo 1 2) is syntactically well-formed but can be evaluated only if foo is the name of a function or macro.
-
-
-
-
41
-
-
84892043281
-
-
One other rarely used kind of Lisp form is a list whose first element is a lambda form. I'll discuss this kind of form in Chapter 5
-
One other rarely used kind of Lisp form is a list whose first element is a lambda form. I'll discuss this kind of form in Chapter 5.
-
-
-
-
42
-
-
84892077680
-
-
One other possibility exists-it's possible to define symbol macros that are evaluated slightly differently. We won't worry about them
-
One other possibility exists-it's possible to define symbol macros that are evaluated slightly differently. We won't worry about them.
-
-
-
-
43
-
-
84957752915
-
-
Common Lisp a symbol can name both an operator-function, macro, or special operator- and a variable. This is one of the major differences between Common Lisp and Scheme. The difference is sometimes described as Common Lisp being a Lisp-2 vs. Scheme being a Lisp-1-a Lisp-2 has two namespaces, one for operators and one for variables, but a Lisp-1 uses a single namespace. Both choices have advantages, and partisans can debate endlessly which is better
-
In Common Lisp a symbol can name both an operator-function, macro, or special operator- and a variable. This is one of the major differences between Common Lisp and Scheme. The difference is sometimes described as Common Lisp being a Lisp-2 vs. Scheme being a Lisp-1-a Lisp-2 has two namespaces, one for operators and one for variables, but a Lisp-1 uses a single namespace. Both choices have advantages, and partisans can debate endlessly which is better.
-
-
-
-
44
-
-
84892139229
-
-
The others provide useful, but somewhat esoteric, features. I'll discuss them as the features they support come up
-
The others provide useful, but somewhat esoteric, features. I'll discuss them as the features they support come up.
-
-
-
-
45
-
-
84957787787
-
-
This syntax is an example of a reader macro. Reader macros modify the syntax the reader uses to translate text into Lisp objects. It is, in fact, possible to define your own reader macros, but that's a rarely used facility of the language. When most Lispers talk about "extending the syntax" of the language, they're talking about regular macros, as I'll discuss in a moment
-
This syntax is an example of a reader macro. Reader macros modify the syntax the reader uses to translate text into Lisp objects. It is, in fact, possible to define your own reader macros, but that's a rarely used facility of the language. When most Lispers talk about "extending the syntax" of the language, they're talking about regular macros, as I'll discuss in a moment.
-
-
-
-
46
-
-
84957767225
-
-
Using the empty list as false is a reflection of Lisp's heritage as a list-processing language much as the use of the integer 0 as false in C is a reflection of its heritage as a bit-twiddling language. Not all Lisps handle boolean values the same way. Another of the many subtle differences upon which a good Common Lisp vs. Scheme flame war can rage for days is Scheme's use of a distinct false value #f, which isn't the same value as either the symbol nil or the empty list, which are also distinct from each other
-
Using the empty list as false is a reflection of Lisp's heritage as a list-processing language much as the use of the integer 0 as false in C is a reflection of its heritage as a bit-twiddling language. Not all Lisps handle boolean values the same way. Another of the many subtle differences upon which a good Common Lisp vs. Scheme flame war can rage for days is Scheme's use of a distinct false value #f, which isn't the same value as either the symbol nil or the empty list, which are also distinct from each other.
-
-
-
-
47
-
-
84957755427
-
-
Even the language standard is a bit ambivalent about which of EQ or EQL should be preferred. Object identity is defined by EQ, but the standard defines the phrase the same when talking about objects to mean EQL unless another predicate is explicitly mentioned. Thus, if you want to be 100 percent technically correct, you can say that - 3 2 and - 4 3 evaluate to "the same" object but not that they evaluate to "identical" objects. This is, admittedly, a bit of an angels-onpinheads kind of issue
-
Even the language standard is a bit ambivalent about which of EQ or EQL should be preferred. Object identity is defined by EQ, but the standard defines the phrase the same when talking about objects to mean EQL unless another predicate is explicitly mentioned. Thus, if you want to be 100 percent technically correct, you can say that (-3 2) and (-4 3) evaluate to "the same" object but not that they evaluate to "identical" objects. This is, admittedly, a bit of an angels-onpinheads kind of issue.
-
-
-
-
48
-
-
84957787393
-
-
Despite the importance of functions in Common Lisp, it isn't really accurate to describe it as a functional language. It's true some of Common Lisp's features, such as its list manipulation functions, are designed to be used in a body-form style and that Lisp has a prominent place in the history of functional programming-McCarthy introduced many ideas that are now considered important in functional programming-but Common Lisp was intentionally designed to support many different styles of programming. In the Lisp family, Scheme is the nearest thing to a "pure" functional language, and even it has several features that disqualify it from absolute purity compared to languages such as Haskell and ML
-
Despite the importance of functions in Common Lisp, it isn't really accurate to describe it as a functional language. It's true some of Common Lisp's features, such as its list manipulation functions, are designed to be used in a body-form style and that Lisp has a prominent place in the history of functional programming-McCarthy introduced many ideas that are now considered important in functional programming-but Common Lisp was intentionally designed to support many different styles of programming. In the Lisp family, Scheme is the nearest thing to a "pure" functional language, and even it has several features that disqualify it from absolute purity compared to languages such as Haskell and ML.
-
-
-
-
49
-
-
84891989888
-
-
Parameter lists are sometimes also called lambda lists because of the historical relationship between Lisp's notion of functions and the lambda calculus
-
Parameter lists are sometimes also called lambda lists because of the historical relationship between Lisp's notion of functions and the lambda calculus.
-
-
-
-
50
-
-
84957762530
-
-
languages that don't support optional parameters directly, programmers typically find ways to simulate them. One technique is to use distinguished "no-value" values that the caller can pass to indicate they want the default value of a given parameter. In C, for example, it's common to use NULL as such a distinguished value. However, such a protocol between the function and its callers is ad hoc-in some functions or for some arguments NULL may be the distinguished value while in other functions or for other arguments the magic value may be-1 or some #defined constant. In languages such as Java that support overloading a single method name with multiple definitions, optional parameters can also be simulated by providing methods with the same name but different numbers of arguments and having the methods with fewer arguments call the "real" method with default values for the missing arguments
-
In languages that don't support optional parameters directly, programmers typically find ways to simulate them. One technique is to use distinguished "no-value" values that the caller can pass to indicate they want the default value of a given parameter. In C, for example, it's common to use NULL as such a distinguished value. However, such a protocol between the function and its callers is ad hoc-in some functions or for some arguments NULL may be the distinguished value while in other functions or for other arguments the magic value may be-1 or some #defined constant. In languages such as Java that support overloading a single method name with multiple definitions, optional parameters can also be simulated by providing methods with the same name but different numbers of arguments and having the methods with fewer arguments call the "real" method with default values for the missing arguments.
-
-
-
-
51
-
-
84892118628
-
-
The constant CALL-ARGUMENTS-LIMIT tells you the implementation-specific value
-
The constant CALL-ARGUMENTS-LIMIT tells you the implementation-specific value.
-
-
-
-
52
-
-
84891981991
-
-
Another macro, RETURN, doesn't require a name. However, you can't use it instead of RETURN-FROM to avoid having to specify the function name; it's syntactic sugar for returning from a block named NIL. I'll cover it, along with the details of BLOCK and RETURN-FROM, in Chapter 20
-
Another macro, RETURN, doesn't require a name. However, you can't use it instead of RETURN-FROM to avoid having to specify the function name; it's syntactic sugar for returning from a block named NIL. I'll cover it, along with the details of BLOCK and RETURN-FROM, in Chapter 20.
-
-
-
-
53
-
-
84957743865
-
-
Lisp, of course, isn't the only language to treat functions as data. C uses function pointers, Perl uses subroutine references, Python uses a scheme similar to Lisp, and C# introduces delegates, essentially typed function pointers, as an improvement over Java's rather clunky reflection and anonymous class mechanisms
-
Lisp, of course, isn't the only language to treat functions as data. C uses function pointers, Perl uses subroutine references, Python uses a scheme similar to Lisp, and C# introduces delegates, essentially typed function pointers, as an improvement over Java's rather clunky reflection and anonymous class mechanisms.
-
-
-
-
54
-
-
84892030959
-
-
The exact printed representation of a function object will differ from implementation to implementation
-
The exact printed representation of a function object will differ from implementation to implementation.
-
-
-
-
55
-
-
84957776080
-
-
The best way to think of FUNCTION is as a special kind of quotation. QUOTEing a symbol prevents it from being evaluated at all, resulting in the symbol itself rather than the value of the variable named by that symbol. FUNCTION also circumvents the normal evaluation rule but, instead of preventing the symbol from being evaluated at all, causes it to be evaluated as the name of a function, just the way it would if it were used as the function name in a function call expression
-
The best way to think of FUNCTION is as a special kind of quotation. QUOTEing a symbol prevents it from being evaluated at all, resulting in the symbol itself rather than the value of the variable named by that symbol. FUNCTION also circumvents the normal evaluation rule but, instead of preventing the symbol from being evaluated at all, causes it to be evaluated as the name of a function, just the way it would if it were used as the function name in a function call expression.
-
-
-
-
56
-
-
84891991575
-
-
There's actually a third, the special operator MULTIPLE-VALUE-CALL, but I'll save that for when I discuss expressions that return multiple values in Chapter 20
-
There's actually a third, the special operator MULTIPLE-VALUE-CALL, but I'll save that for when I discuss expressions that return multiple values in Chapter 20.
-
-
-
-
57
-
-
84892028530
-
-
Most folks either always use #' before LAMBDA expressions in value positions or never do. In this book, I always use #'
-
In Common Lisp it's also possible to use a LAMBDA expression as an argument to FUNCALL (or some other function that takes a function argument such as SORT or MAPCAR) with no #' before it, like this: (funcall (lambda (x y) (+ x y)) 2 3) This is legal and is equivalent to the version with the #' but for a tricky reason. Historically, LAMBDA expressions by themselves weren't expressions that could be evaluated. That is, LAMBDA wasn't the name of a function, macro, or special operator. Rather, a list starting with the symbol LAMBDA was a special syntactic construct that Lisp recognized as a kind of function name. But if that were still true, then (funcall (lambda (...)...)) would be illegal because FUNCALL is a function and the normal evaluation rule for a function call would require that the LAMBDA expression be evaluated. However, late in the ANSI standardization process, in order to make it possible to implement ISLISP, another Lisp dialect being standardized at the same time, strictly as a user-level compatibility layer on top of Common Lisp, a LAMBDA macro was defined that expands into a call to FUNCTION wrapped around the LAMBDA expression. In other words, the following LAMBDA expression: (lambda () 42) expands into the following when it occurs in a context where it's evaluated: (function (lambda () 42)); or #' (lambda () 42) This makes its use in a value position, such as an argument to FUNCALL, legal. In other words, it's pure syntactic sugar. Most folks either always use #' before LAMBDA expressions in value positions or never do. In this book, I always use #'.
-
-
-
-
58
-
-
84957755223
-
-
Early Lisps tended to use dynamic variables for local variables, at least when interpreted. Elisp, the Lisp dialect used in Emacs, is a bit of a throwback in this respect, continuing to support only dynamic variables. Other languages have recapitulated this transition from dynamic to lexical variables-Perl's local variables, for instance, are dynamic while its my variables, introduced in Perl 5, are lexical. Python never had true dynamic variables but only introduced true lexical scoping in version 2.2. Python's lexical variables are still somewhat limited compared to Lisp's because of the conflation of assignment and binding in the language's syntax.
-
Early Lisps tended to use dynamic variables for local variables, at least when interpreted. Elisp, the Lisp dialect used in Emacs, is a bit of a throwback in this respect, continuing to support only dynamic variables. Other languages have recapitulated this transition from dynamic to lexical variables-Perl's local variables, for instance, are dynamic while its my variables, introduced in Perl 5, are lexical. Python never had true dynamic variables but only introduced true lexical scoping in version 2.2. (Python's lexical variables are still somewhat limited compared to Lisp's because of the conflation of assignment and binding in the language's syntax.)
-
-
-
-
59
-
-
84957747650
-
-
Actually, it's not quite true to say that all type errors will always be detected-it's possible to use optional declarations to tell the compiler that certain variables will always contain objects of a particular type and to turn off runtime type checking in certain regions of code. However, declarations of this sort are used to optimize code after it has been developed and debugged, not during normal development
-
Actually, it's not quite true to say that all type errors will always be detected-it's possible to use optional declarations to tell the compiler that certain variables will always contain objects of a particular type and to turn off runtime type checking in certain regions of code. However, declarations of this sort are used to optimize code after it has been developed and debugged, not during normal development.
-
-
-
-
60
-
-
84957768738
-
-
As an optimization certain kinds of objects, such as integers below a certain size and characters, may be represented directly in memory where other objects would be represented by a pointer to the actual object. However, since integers and characters are immutable, it doesn't matter that there may be multiple copies of "the same" object in different variables. This is the root of the difference between EQ and EQL discussed in Chapter 4
-
As an optimization certain kinds of objects, such as integers below a certain size and characters, may be represented directly in memory where other objects would be represented by a pointer to the actual object. However, since integers and characters are immutable, it doesn't matter that there may be multiple copies of "the same" object in different variables. This is the root of the difference between EQ and EQL discussed in Chapter 4.
-
-
-
-
61
-
-
84892050991
-
-
compiler-writer terms Common Lisp functions are "pass-by-value. " However, the values that are passed are references to objects. This is similar to how Java and Python work
-
In compiler-writer terms Common Lisp functions are "pass-by-value. " However, the values that are passed are references to objects. This is similar to how Java and Python work.
-
-
-
-
62
-
-
84957776490
-
-
The variables in LET forms and function parameters are created by exactly the same mechanism. In fact, in some Lisp dialects-though not Common Lisp-LET is simply a macro that expands into a call to an anonymous function. That is, in those dialects, the following: let x 10 format t "-a" x is a macro form that expands into this: lambda x format t "-a" x 10
-
The variables in LET forms and function parameters are created by exactly the same mechanism. In fact, in some Lisp dialects-though not Common Lisp-LET is simply a macro that expands into a call to an anonymous function. That is, in those dialects, the following: (let ((x 10)) (format t "-a" x)) is a macro form that expands into this: ((lambda (x) (format t "-a" x)) 10)
-
-
-
-
63
-
-
84891966596
-
-
Java disguises global variables as public static fields, C uses extern variables, and Python's module-level and Perl's package-level variables can likewise be accessed from anywhere
-
Java disguises global variables as public static fields, C uses extern variables, and Python's module-level and Perl's package-level variables can likewise be accessed from anywhere.
-
-
-
-
64
-
-
84892030097
-
-
If you specifically want to reset a DEFVARed variable, you can either set it directly with SETF or make it unbound using MAKUNBOUND and then reevaluate the DEFVAR form
-
If you specifically want to reset a DEFVARed variable, you can either set it directly with SETF or make it unbound using MAKUNBOUND and then reevaluate the DEFVAR form.
-
-
-
-
65
-
-
84957749692
-
-
The strategy of temporarily reassigning standard-output also breaks if the system is multithreaded-if there are multiple threads of control trying to print to different streams at the same time, they'll all try to set the global variable to the stream they want to use, stomping all over each other. You could use a lock to control access to the global variable, but then you're not really getting the benefit of multiple concurrent threads, since whatever thread is printing has to lock out all the other threads until it's done even if they want to print to a different stream
-
The strategy of temporarily reassigning standard-output also breaks if the system is multithreaded-if there are multiple threads of control trying to print to different streams at the same time, they'll all try to set the global variable to the stream they want to use, stomping all over each other. You could use a lock to control access to the global variable, but then you're not really getting the benefit of multiple concurrent threads, since whatever thread is printing has to lock out all the other threads until it's done even if they want to print to a different stream.
-
-
-
-
66
-
-
84957741900
-
-
The technical term for the interval during which references may be made to a binding is its extent. Thus, scope and extent are complementary notions-scope refers to space while extent refers to time. Lexical variables have lexical scope but indefinite extent, meaning they stick around for an indefinite interval, determined by how long they're needed. Dynamic variables, by contrast, have indefinite scope since they can be referred to from anywhere but dynamic extent. To further confuse matters, the combination of indefinite scope and dynamic extent is frequently referred to by the misnomer dynamic scope
-
The technical term for the interval during which references may be made to a binding is its extent. Thus, scope and extent are complementary notions-scope refers to space while extent refers to time. Lexical variables have lexical scope but indefinite extent, meaning they stick around for an indefinite interval, determined by how long they're needed. Dynamic variables, by contrast, have indefinite scope since they can be referred to from anywhere but dynamic extent. To further confuse matters, the combination of indefinite scope and dynamic extent is frequently referred to by the misnomer dynamic scope.
-
-
-
-
67
-
-
84957737116
-
-
Though the standard doesn't specify how to incorporate multithreading into Common Lisp, implementations that provide multithreading follow the practice established on the Lisp machines and create dynamic bindings on a per-thread basis. A reference to a global variable will find the binding most recently established in the current thread, or the global binding
-
Though the standard doesn't specify how to incorporate multithreading into Common Lisp, implementations that provide multithreading follow the practice established on the Lisp machines and create dynamic bindings on a per-thread basis. A reference to a global variable will find the binding most recently established in the current thread, or the global binding.
-
-
-
-
68
-
-
84891983497
-
-
This is why dynamic variables are also sometimes called special variables
-
This is why dynamic variables are also sometimes called special variables.
-
-
-
-
69
-
-
84892020048
-
-
If you must know, you can look up DECLARE, SPECIAL, and LOCALLY in the HyperSpec
-
If you must know, you can look up DECLARE, SPECIAL, and LOCALLY in the HyperSpec.
-
-
-
-
70
-
-
84891990708
-
-
Several key constants defined by the language itself don't follow this convention-not least of which are T and NIL. This is occasionally annoying when one wants to use t as a local variable name. Another is PI, which holds the best long-float approximation of the mathematical constant π
-
Several key constants defined by the language itself don't follow this convention-not least of which are T and NIL. This is occasionally annoying when one wants to use t as a local variable name. Another is PI, which holds the best long-float approximation of the mathematical constant π.
-
-
-
-
71
-
-
84892025293
-
-
Some old-school Lispers prefer to use SETQ with variables, but modern style tends to use SETF for all assignments
-
Some old-school Lispers prefer to use SETQ with variables, but modern style tends to use SETF for all assignments.
-
-
-
-
72
-
-
84892116230
-
-
Look up DEFSETF, DEFINE-SETF-EXPANDER for more information
-
Look up DEFSETF, DEFINE-SETF-EXPANDER for more information.
-
-
-
-
73
-
-
84957770613
-
-
The prevalence of Algol-derived syntax for assignment with the "place" on the left side of the = and the new value on the right side has spawned the terminology lvalue, short for "left value", meaning something that can be assigned to, and rvalue, meaning something that provides a value. A compiler hacker would say, "SETF treats its first argument as an lvalue"
-
The prevalence of Algol-derived syntax for assignment with the "place" on the left side of the = and the new value on the right side has spawned the terminology lvalue, short for "left value", meaning something that can be assigned to, and rvalue, meaning something that provides a value. A compiler hacker would say, "SETF treats its first argument as an lvalue"
-
-
-
-
74
-
-
84957772384
-
-
C programmers may want to think of variables and other places as holding a pointer to the real object; assigning to a variable simply changes what object it points to while assigning to a part of a composite object is similar to indirecting through the pointer to the actual object. C++ programmers should note that the behavior of = in C++ when dealing with objects-namely, a memberwise copy-is quite idiosyncratic
-
C programmers may want to think of variables and other places as holding a pointer to the real object; assigning to a variable simply changes what object it points to while assigning to a part of a composite object is similar to indirecting through the pointer to the actual object. C++ programmers should note that the behavior of = in C++ when dealing with objects-namely, a memberwise copy-is quite idiosyncratic.
-
-
-
-
75
-
-
84892009510
-
-
Another important class of language constructs that are defined using macros are all the definitional constructs such as DEFUN, DEFPARAMETER, DEFVAR, and others. In Chapter 24 you'll define your own definitional macros that will allow you to concisely write code for reading and writing binary data
-
Another important class of language constructs that are defined using macros are all the definitional constructs such as DEFUN, DEFPARAMETER, DEFVAR, and others. In Chapter 24 you'll define your own definitional macros that will allow you to concisely write code for reading and writing binary data.
-
-
-
-
76
-
-
84892082130
-
-
You can't actually feed this definition to Lisp because it's illegal to redefine names in the COMMON-LISP package where WHEN comes from. If you really want to try writing such a macro, you'd need to change the name to something else, such as my-when
-
You can't actually feed this definition to Lisp because it's illegal to redefine names in the COMMON-LISP package where WHEN comes from. If you really want to try writing such a macro, you'd need to change the name to something else, such as my-when.
-
-
-
-
77
-
-
84891973886
-
-
The special operators, if you must know, are TAGBODY and GO. There's no need to discuss them now, but I'll cover them in Chapter 20
-
The special operators, if you must know, are TAGBODY and GO. There's no need to discuss them now, but I'll cover them in Chapter 20.
-
-
-
-
78
-
-
84892094460
-
-
A variant of DO, DO, assigns each variable its value before evaluating the step form for subsequent variables. For more details, consult your favorite Common Lisp reference
-
A variant of DO, DO, assigns each variable its value before evaluating the step form for subsequent variables. For more details, consult your favorite Common Lisp reference.
-
-
-
-
79
-
-
84892002434
-
-
The DOTIMES is also preferred because the macro expansion will likely include declarations that allow the compiler to generate more efficient code
-
The DOTIMES is also preferred because the macro expansion will likely include declarations that allow the compiler to generate more efficient code.
-
-
-
-
80
-
-
84957731569
-
-
Loop keywords is a bit of a misnomer since they aren't keyword symbols. In fact, LOOP doesn't care what package the symbols are from. When the LOOP macro parses its body, it considers any appropriately named symbols equivalent. You could even use true keywords if you wanted-: for: across, and so on-because they also have the correct name. But most folks just use plain symbols. Because the loop keywords are used only as syntactic markers, it doesn't matter if they're used for other purposes-as function or variable names
-
Loop keywords is a bit of a misnomer since they aren't keyword symbols. In fact, LOOP doesn't care what package the symbols are from. When the LOOP macro parses its body, it considers any appropriately named symbols equivalent. You could even use true keywords if you wanted-:for: across, and so on-because they also have the correct name. But most folks just use plain symbols. Because the loop keywords are used only as syntactic markers, it doesn't matter if they're used for other purposes-as function or variable names.
-
-
-
-
81
-
-
84892117466
-
-
As with functions, macros can also contain declarations, but you don't need to worry about those for now
-
As with functions, macros can also contain declarations, but you don't need to worry about those for now.
-
-
-
-
82
-
-
84892064497
-
-
APPEND, which I haven't discussed yet, is a function that takes any number of list arguments and returns the result of splicing them together into a single list
-
APPEND, which I haven't discussed yet, is a function that takes any number of list arguments and returns the result of splicing them together into a single list.
-
-
-
-
83
-
-
84892038361
-
-
If the macro expansion is shown all on one line, it's probably because the variable PRINT-PRETTY is NIL. If it is, evaluating setf print-pretty t should make the macro expansion easier to read
-
If the macro expansion is shown all on one line, it's probably because the variable PRINT-PRETTY is NIL. If it is, evaluating (setf print-pretty t) should make the macro expansion easier to read.
-
-
-
-
84
-
-
84891980568
-
-
This is from Joel on Software by Joel Spolsky, also available at http://www.joelonsoftware.com/articles/LeakyAbstractions.html. Spolsky's point in the essay is that all abstractions leak to some extent; that is, there are no perfect abstractions. But that doesn't mean you should tolerate leaks you can easily plug.
-
-
-
-
85
-
-
84892025765
-
-
Of course, certain forms are supposed to be evaluated more than once, such as the forms in the body of a do-primes loop
-
Of course, certain forms are supposed to be evaluated more than once, such as the forms in the body of a do-primes loop.
-
-
-
-
86
-
-
84957762016
-
-
It may not be obvious that this loop is necessarily infinite given the nonuniform occurrences of prime numbers. The starting point for a proof that it is in fact infinite is Bertrand's postulate, which says for any n > 1, there exists a prime p, n < p < 2n. From there you can prove that for any prime number, P less than the sum of the preceding prime numbers, the next prime, P', is also smaller than the original sum plus P
-
It may not be obvious that this loop is necessarily infinite given the nonuniform occurrences of prime numbers. The starting point for a proof that it is in fact infinite is Bertrand's postulate, which says for any n > 1, there exists a prime p, n < p < 2n. From there you can prove that for any prime number, P less than the sum of the preceding prime numbers, the next prime, P', is also smaller than the original sum plus P.
-
-
-
-
87
-
-
84957757516
-
-
This is for illustrative purposes only-obviously, writing test cases for built-in functions such as + is a bit silly, since if such basic things aren't working, the chances the tests will be running the way you expect is pretty slim. On the other hand, most Common Lisps are implemented largely in Common Lisp, so it's not crazy to imagine writing test suites in Common Lisp to test the standard library functions
-
This is for illustrative purposes only-obviously, writing test cases for built-in functions such as + is a bit silly, since if such basic things aren't working, the chances the tests will be running the way you expect is pretty slim. On the other hand, most Common Lisps are implemented largely in Common Lisp, so it's not crazy to imagine writing test suites in Common Lisp to test the standard library functions.
-
-
-
-
88
-
-
84892133476
-
-
Side effects can include such things as signaling errors; I'll discuss Common Lisp's error handling system in Chapter 19. You may, after reading that chapter, want to think about how to incorporate tests that check whether a function does or does not signal a particular error in certain situations
-
Side effects can include such things as signaling errors; I'll discuss Common Lisp's error handling system in Chapter 19. You may, after reading that chapter, want to think about how to incorporate tests that check whether a function does or does not signal a particular error in certain situations.
-
-
-
-
89
-
-
84891977209
-
-
I'll discuss this and other FORMAT directives in more detail in Chapter 18
-
I'll discuss this and other FORMAT directives in more detail in Chapter 18.
-
-
-
-
90
-
-
84892122674
-
-
You have to change the test to make it fail since you can't change the behavior of +
-
You have to change the test to make it fail since you can't change the behavior of +.
-
-
-
-
91
-
-
84891978509
-
-
Though, again, if the test functions have been compiled, you'll have to recompile them after changing the macro
-
Though, again, if the test functions have been compiled, you'll have to recompile them after changing the macro.
-
-
-
|