Книга: Practical Common Lisp
Setting Up and Tearing Down
Setting Up and Tearing Down
One of the key insights the designers of the LOOP
language had about actual loops "in the wild" is that the loop proper is often preceded by a bit of code to set things up and then followed by some more code that does something with the values computed by the loop. A trivial example, in Perl,[241] might look like this:
my $evens_sum = 0;
my $odds_sum = 0;
foreach my $i (@list_of_numbers) {
if ($i % 2) {
$odds_sum += $i;
} else {
$evens_sum += $i;
}
}
if ($evens_sum > $odds_sum) {
print "Sum of evens greatern";
} else {
print "Sum of odds greatern";
}
The loop proper in this code is the foreach
statement. But the foreach
loop doesn't stand on its own: the code in the loop body refers to variables declared in the two lines before the loop.[242] And the work the loop does is all for naught without the if
statement after the loop that actually reports the results. In Common Lisp, of course, the LOOP
construct is an expression that returns a value, so there's even more often a need to do something after the loop proper, namely, generate the return value.
So, said the LOOP
designers, let's give a way to include the code that's really part of the loop in the loop itself. Thus, LOOP
provides two keywords, initially
and finally
, that introduce code to be run outside the loop's main body.
After the initially
or finally
, these clauses consist of all the Lisp forms up to the start of the next loop clause or the end of the loop. All the initially
forms are combined into a single prologue, which runs once, immediately after all the local loop variables are initialized and before the body of the loop. The finally
forms are similarly combined into a epilogue to be run after the last iteration of the loop body. Both the prologue and epilogue code can refer to local loop variables.
The prologue is always run, even if the loop body iterates zero times. The loop can return without running the epilogue if any of the following happens:
• A return
clause executes.
• RETURN
, RETURN-FROM
, or another transfer of control construct is called from within a Lisp form within the body.[243]
• The loop is terminated by an always
, never
, or thereis
clause, as I'll discuss in the next section.
Within the epilogue code, RETURN
or RETURN-FROM
can be used to explicitly provide a return value for the loop. Such an explicit return value will take precedence over any value that might otherwise be provided by an accumulation or termination test clause.
To allow RETURN-FROM
to be used to return from a specific loop (useful when nesting LOOP
expressions), you can name a LOOP
with the loop keyword named
. If a named
clause appears in a loop, it must be the first clause. For a simple example, assume lists
is a list of lists and you want to find an item that matches some criteria in one of those nested lists. You could find it with a pair of nested loops like this:
(loop named outer for list in lists do
(loop for item in list do
(if (what-i-am-looking-for-p item)
(return-from outer item))))
- Разработка приложений баз данных InterBase на Borland Delphi
- Open Source Insight and Discussion
- Introduction to Microprocessors and Microcontrollers
- Chapter 6. Traversing of tables and chains
- Chapter 8. Saving and restoring large rule-sets
- Chapter 11. Iptables targets and jumps
- Chapter 5 Installing and Configuring VirtualCenter 2.0
- Chapter 16. Commercial products based on Linux, iptables and netfilter
- Appendix A. Detailed explanations of special commands
- Appendix B. Common problems and questions
- Appendix E. Other resources and links
- IP filtering terms and expressions