forked from xach/dpans
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconcept-loop.tex
2389 lines (1964 loc) · 86.6 KB
/
concept-loop.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% -*- Mode: TeX -*-
\beginsubsection{Overview of the Loop Facility}
\Themacro{loop} performs iteration.
\beginsubsubsection{Simple vs Extended Loop}
\macref{loop} \term{forms} are partitioned into two categories:
simple \macref{loop} \term{forms}
and extended \macref{loop} \term{forms}.
\beginsubsubsubsection{Simple Loop}
\DefineSection{SimpleLoop}
A simple \macref{loop} \term{form} is one that has a body containing
only \term{compound forms}.
%% 7.8.1 3
Each \term{form} is \term{evaluated} in turn from left to right.
When the last \param{form} has been \term{evaluated},
then the first \param{form} is evaluated again, and so on, in a never-ending cycle.
%% 7.8.1 4
A simple \macref{loop} \term{form} establishes an \term{implicit block} named \nil.
The execution of a simple \macref{loop} can be terminated by explicitly
transfering control to the \term{implicit block} (using \macref{return} or
\specref{return-from}) or to some \term{exit point} outside of the \term{block}
(\eg using \specref{throw}, \specref{go}, or \specref{return-from}).
%KMP: What about LOOP-FINISH here?
% Test cases: (loop (loop-finish)) and (loop do (loop (loop-finish))).
% Mail sent to X3J13 saying I was going to make this explicitly vague,
% since some implementations
% See the LOOP-FINISH dictionary entry.
\endsubsubsubsection%{Simple Loop}
%========================================
\beginsubsubsubsection{Extended Loop}
An extended \macref{loop} \term{form} is one that has a body containing
\term{atomic} \term{expressions}. When \themacro{loop} processes such a
\term{form}, it invokes a facility that is commonly called ``the Loop Facility.''
The Loop Facility provides standardized access to mechanisms commonly used
in iterations through Loop schemas, which are introduced by \term{loop keywords}.
The body of an extended \macref{loop} \term{form} is divided into \macref{loop} clauses,
each which is in turn made up of \term{loop keywords} and \term{forms}.
\endsubsubsubsection%{Extended Loop}
\endsubsubsection%{Simple vs Extended Loop}
\beginsubsubsection{Loop Keywords}
%2
\term{Loop keywords} are not true \term{keywords}\meaning{1};
they are special \term{symbols}, recognized by \term{name} rather than \term{object} identity,
that are meaningful only to the \macref{loop} facility.
A \term{loop keyword} is a \term{symbol} but is recognized by its \term{name}
(not its identity), regardless of the \term{packages} in which it is \term{accessible}.
\issue{JUN90-TRIVIAL-ISSUES:11}
In general, \term{loop keywords} are not \term{external symbols} of \thepackage{common-lisp},
except in the coincidental situation that a \term{symbol} with the same name as a
\term{loop keyword} was needed for some other purpose in \clisp. For example,
there is a \term{symbol} in \thepackage{common-lisp} whose \term{name} is \f{"UNLESS"} but
not one whose \term{name} is \f{"UNTIL"}.
\endissue{JUN90-TRIVIAL-ISSUES:11}
If no \term{loop keywords} are supplied in a \macref{loop} \term{form},
the Loop Facility executes the loop body repeatedly; \seesection\SimpleLoop.
\endsubsubsection%{Loop Keywords}
\beginsubsubsection{Parsing Loop Clauses}
%7
The syntactic parts of an extended \macref{loop} \term{form} are called clauses;
%the scope \reviewer{Barmar: what meaning of scope?}%!!!
%of each clause
the rules for parsing are determined by
%the parsing of
that clause's keyword.
The following example shows a \macref{loop} \term{form} with six clauses:
\code
(loop for i from 1 to (compute-top-value) ; first clause
while (not (unacceptable i)) ; second clause
collect (square i) ; third clause
do (format t "Working on ~D now" i) ; fourth clause
when (evenp i) ; fifth clause
do (format t "~D is a non-odd number" i)
finally (format t "About to exit!")) ; sixth clause
\endcode
%8
Each \term{loop keyword} introduces
either a compound loop clause or a simple loop clause
that can consist of a \term{loop keyword} followed by a single \term{form}.
The number of \term{forms} in a clause is determined by the \term{loop keyword}
that begins the clause and by the auxiliary keywords in the clause.
The keywords \loopref{do},
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
\loopref{doing},
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
\loopref{initially}, and \loopref{finally}
are the only loop keywords that can take any number of \term{forms} and
group them as an \term{implicit progn}.
%9
Loop clauses can contain auxiliary keywords, which are sometimes
called prepositions. For example, the first clause in the code
above includes the prepositions \loopref{from} and \loopref{to},
which mark the value from which stepping begins and the value at which stepping
ends.
For detailed information about \macref{loop} syntax,
\seemac{loop}.
\endsubsubsection%{Parsing Loop Clauses}
\beginsubsubsection{Expanding Loop Forms}
%!!! Barmar: This seems to legislate the implementation. We should define the meaning
% and let the implementors worry about how to code it.
%3
A \macref{loop} \term{macro form} expands into a \term{form} containing
%one or more \term{lambda expressions} for the local \term{binding} of loop variables
one or more binding forms (that \term{establish} \term{bindings} of loop variables)
and a \specref{block} and a \specref{tagbody} (that express a looping control
structure). The variables established in \macref{loop} are bound as
if by \specref{let} or \misc{lambda}.
Implementations can interleave the setting of initial values with the \term{bindings}.
However, the assignment of the initial values is always calculated in the order
specified by the user. A variable is thus sometimes bound to a meaningless value
of the correct \term{type}, and then later in the prologue it is set to the true
initial value by using \specref{setq}.
\issue{LOOP-INITFORM-ENVIRONMENT:PARTIAL-INTERLEAVING-VAGUE}
One implication of this interleaving is that it is \term{implementation-dependent}
whether the \term{lexical environment} in which the initial value \term{forms}
(variously called the \param{form1}, \param{form2}, \param{form3}, \param{step-fun},
\param{vector}, \param{hash-table}, and \param{package}) in any \param{for-as-subclause},
except \param{for-as-equals-then},
are \term{evaluated} includes only the loop variables preceding that \term{form}
or includes more or all of the loop variables;
the \param{form1} and \param{form2} in a \param{for-as-equals-then} form
includes the \term{lexical environment} of all the loop variables.
\endissue{LOOP-INITFORM-ENVIRONMENT:PARTIAL-INTERLEAVING-VAGUE}
%4
After the \term{form} is expanded, it consists of three basic parts in the
\specref{tagbody}:
the loop prologue,
the loop body,
and the loop epilogue.
\beginlist
\itemitem{\b{Loop prologue}}
The loop prologue contains \term{forms}
that are executed before iteration begins, such as
any automatic variable initializations prescribed
by the \param{variable} clauses, along with any \loopref{initially} clauses
in the order they appear in the source.
\itemitem{\b{Loop body}}
The loop body contains those \term{forms} that are executed during iteration,
including application-specific calculations, termination tests,
and variable \term{stepping}\meaning{1}.
\itemitem{\b{Loop epilogue}}
The loop epilogue contains \term{forms} that are executed after iteration
terminates, such as \loopref{finally} clauses, if any, along
with any implicit return value from an \param{accumulation} clause or
an \param{termination-test} clause.
\endlist
%5
Some clauses from the source \term{form}
contribute code only to the loop prologue; these clauses must
come before other clauses that are in the main body of the \macref{loop} form.
Others contribute code only to the loop epilogue.
All other clauses contribute to the final
translated \term{form} in the same
order given in the original source \term{form} of the \macref{loop}.
%6
Expansion of the \macref{loop} macro produces an \term{implicit block} named \nil\
\issue{LOOP-NAMED-BLOCK-NIL:OVERRIDE}
unless \loopref{named} is supplied.
\endissue{LOOP-NAMED-BLOCK-NIL:OVERRIDE}
Thus, \specref{return-from} (and sometimes \macref{return})
can be used to return values from \macref{loop} or to exit \macref{loop}.
%%Barmar: Has nothing to do with LOOP specifically.
% Within the executable parts of loop clauses and around the entire
% \macref{loop} form, variables can be bound by using \specref{let}.
\endsubsubsection%{Expanding Loop Forms}
\beginsubsubsection{Summary of Loop Clauses}
%11
Loop clauses fall into one of the following categories:
\beginsubsubsubsection{Summary of Variable Initialization and Stepping Clauses}
The \loopref{for} and \loopref{as} constructs provide iteration control clauses
that establish a variable to be initialized.
\loopref{for} and \loopref{as} clauses can be combined with the loop
keyword \loopref{and} to get \term{parallel} initialization and \term{stepping}\meaning{1}.
Otherwise, the initialization and \term{stepping}\meaning{1} are \term{sequential}.
%\issue{LOOP-AND-DISCREPANCY:NO-REITERATION}
% When two or more such clauses are joined with \loopref{and},
% clauses after the first do not have \loopref{for} or \loopref{as} before them.
%\endissue{LOOP-AND-DISCREPANCY:NO-REITERATION}
The \loopref{with} construct is similar to a single \specref{let} clause.
\loopref{with} clauses can be combined using the \term{loop keyword} \loopref{and}
to get \term{parallel} initialization.
%% Removed per Barmar. See Termination Clauses.
% The \loopref{repeat} construct causes iteration to terminate after
% a specified number of times. It uses an internal variable
% to keep track of the number of iterations.
For more information, \seesection\LOOPVarInitAndStep.
\endsubsubsubsection%{Summary of Variable Initialization and Stepping Clauses}
\beginsubsubsubsection{Summary of Value Accumulation Clauses}
The \loopref{collect} (or \loopref{collecting}) construct
takes one \term{form} in its clause
and adds the value of that \term{form} to the end of a \term{list}
of values. By default, the \term{list} of values is returned
when the \macref{loop} finishes.
The \loopref{append} (or \loopref{appending}) construct
takes one \term{form} in its clause
and appends the value of that \term{form} to the end of a \term{list}
of values. By default, the \term{list} of values is returned when the
\macref{loop} finishes.
The \loopref{nconc} (or \loopref{nconcing}) construct
is similar to the \loopref{append} construct,
but its \term{list} values are concatenated as if by the function
\loopref{nconc}. By default, the \term{list} of values is returned when
the \macref{loop} finishes.
The \loopref{sum} (or \loopref{summing}) construct
takes one \term{form} in its clause
that must evaluate to a \term{number} and accumulates the sum of all these
\term{numbers}. By default, the cumulative sum is returned when the
\macref{loop} finishes.
The \loopref{count} (or \loopref{counting}) construct
takes one \term{form} in its clause
and counts the number of times that the \term{form} evaluates to \term{true}.
By default, the count is returned when the \macref{loop} finishes.
The \loopref{minimize} (or \loopref{minimizing}) construct
takes one \term{form} in its clause
and determines the minimum value obtained by evaluating that \term{form}.
By default, the minimum value is returned when the \macref{loop} finishes.
The \loopref{maximize} (or \loopref{maximizing}) construct
takes one \term{form} in its clause
and determines the maximum value obtained by evaluating that \term{form}.
By default, the maximum value is returned when the \macref{loop} finishes.
For more information, \seesection\LOOPValAcc.
\endsubsubsubsection%{Summary of Value Accumulation Clauses}
\beginsubsubsubsection{Summary of Termination Test Clauses}
The \loopref{for} and \loopref{as} constructs provide a termination test
that is determined by the iteration control clause.
The \loopref{repeat} construct causes termination after a specified
number of iterations.
%Moved from text removed by Barmar above, so it doesn't get lost. -kmp 30-Jul-91
(It uses an internal variable to keep track of the number of iterations.)
The \loopref{while} construct takes one \term{form}, a \param{test},
and terminates the iteration if the \param{test} evaluates to \term{false}.
%!!! Barmar thinks this is not necessary:
A \loopref{while} clause is equivalent to the expression
\f{(if (not \param{test}) (loop-finish))}.
The \loopref{until} construct is the inverse of \loopref{while};
it terminates the iteration if the \param{test} evaluates to
any \term{non-nil} value.
%!!! Barmar thinks this is not necessary:
An \loopref{until} clause is equivalent to the expression
\hbox{\f{(if \param{test} (loop-finish))}}.
The \loopref{always} construct takes one \term{form} and
terminates the \macref{loop} if the \term{form} ever evaluates to \term{false};
in this case, the \macref{loop} \term{form} returns \nil.
Otherwise, it provides a default return value of \t.
The \loopref{never} construct takes one \term{form} and
terminates the \macref{loop} if the \term{form} ever evaluates to \term{true};
in this case, the \macref{loop} \term{form} returns \nil.
Otherwise, it provides a default return value of \t.
The \loopref{thereis} construct takes one \term{form} and
terminates the \macref{loop} if the \term{form} ever evaluates to
a \term{non-nil} \term{object};
in this case, the \macref{loop} \term{form} returns that \term{object}.
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
Otherwise, it provides a default return value of \nil.
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
%Added per Barmar:
If multiple termination test clauses are specified,
the \macref{loop} \term{form} terminates if any are satisfied.
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
% Note also that the \macref{loop-finish} macro terminates iteration and returns any
% accumulated result. Any \loopref{finally} clauses that are supplied are evaluated.
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
For more information, \seesection\LOOPTermTest.
\endsubsubsubsection%{Summary of Termination Test Clauses}
\beginsubsubsubsection{Summary of Unconditional Execution Clauses}
The \loopref{do} (or \loopref{doing}) construct evaluates all \term{forms} in its clause.
The \loopref{return} construct takes one
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
% \term{form} and returns its value.
\term{form}. Any \term{values} returned by the \term{form} are
immediately returned by the \macref{loop} form.
% It is equivalent to the clause \f{do (return \i{value})}.
It is equivalent to the clause
\f{do (return-from \i{block-name} \i{value})},
where \i{block-name} is the name specified in a \loopref{named}
clause, or \nil\ if there is no \loopref{named} clause.
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
For more information, \seesection\LOOPUnconditional.
\endsubsubsubsection%{Summary of Unconditional Execution Clauses}
\beginsubsubsubsection{Summary of Conditional Execution Clauses}
The \loopref{if} and \loopref{when} constructs take one \term{form} as a test
and a clause that is executed when the test \term{yields} \term{true}.
The clause can be a value accumulation, unconditional, or
another conditional clause; it can also be any combination
of such clauses connected by \theloopkeyword{and}.
\Theloopconstruct{unless} is similar to \theloopconstruct{when}
except that it complements the test result.
\Theloopconstruct{else} provides an optional component of \loopref{if},
\loopref{when}, and \loopref{unless} clauses that is executed
when an \loopref{if} or \loopref{when} test \term{yields} \term{false}
or when an \loopref{unless} test \term{yields} \term{true}.
The component is one of the clauses described under \loopref{if}.
\Theloopconstruct{end} provides an optional component to mark the
end of a conditional clause.
For more information, \seesection\LOOPConditional.
\endsubsubsubsection%{Summary of Conditional Execution Clauses}
\beginsubsubsubsection{Summary of Miscellaneous Clauses}
\Theloopconstruct{named} gives a name for the \term{block} of the loop.
\Theloopconstruct{initially} causes its \term{forms} to be
evaluated in the loop prologue, which precedes all \macref{loop} code
except for initial settings supplied by the constructs \loopref{with},
\loopref{for}, or \loopref{as}.
\Theloopconstruct{finally} causes its \term{forms} to
be evaluated in the loop epilogue after normal iteration terminates.
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
% An unconditional clause can also follow \theloopkeyword{finally}.
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
For more information, \seesection\LOOPMisc.
\endsubsubsubsection%{Summary of Miscellaneous Clauses}
\endsubsubsection%{Summary of Loop Clauses}
\beginsubsubsection{Order of Execution}\idxtext{order of evaluation}\idxtext{evaluation order}
%10
With the exceptions listed below, clauses are executed in the loop body
in the order in which they appear in the source. Execution is repeated
until a clause
terminates the \macref{loop} or until a \macref{return}, \specref{go},
or \specref{throw} form is encountered
%I added this next. -kmp 10-Feb-92
which transfers control to a point outside of the loop.
The following actions are
exceptions to the linear order of execution:
\beginlist
\itemitem{\bull} All variables are initialized first,
regardless of where the establishing clauses appear in the
source. The order of initialization follows the order of these clauses.
\itemitem{\bull} The code for any \loopref{initially} clauses is collected
into one \specref{progn} in the order in which the clauses appear in
the source. The collected code is executed once in the loop prologue
after any implicit variable initializations.
\itemitem{\bull} The code for any \loopref{finally} clauses is collected
into one \specref{progn} in the order in which the clauses appear in
the source. The collected code is executed once in the loop epilogue
before any implicit values from the accumulation clauses are returned.
Explicit returns anywhere in the source, however, will exit the
\macref{loop} without executing the epilogue code.
\itemitem{\bull} A \loopref{with} clause introduces a variable \term{binding}
and an optional initial value. The initial values are calculated
in the order in which the \loopref{with} clauses occur.
\itemitem{\bull}
Iteration control clauses implicitly perform the following actions:
\beginlist
\itemitem{--} initialize variables;
\itemitem{--} \term{step} variables, generally
between each execution of the loop body;
\itemitem{--} perform termination tests,
generally just before the execution of the
loop body.
\endlist
\endlist
\endsubsubsection%{Order of Execution}
\beginsubsubsection{Destructuring}
\DefineSection{DestructuringLOOPVars}
The \param{d-type-spec} argument is used for destructuring.
If the
\param{d-type-spec} argument consists solely of \thetype{fixnum},
\typeref{float}, \typeref{t}, or \nil, the \loopref{of-type} keyword is optional.
The \loopref{of-type} construct is optional in these cases to provide backwards
compatibility; thus, the following two expressions are the same:
%!!! Barmar: Examples belong in the examples section
\code
;;; This expression uses the old syntax for type specifiers.
(loop for i fixnum upfrom 3 ...)
;;; This expression uses the new syntax for type specifiers.
(loop for i of-type fixnum upfrom 3 ...)
;; Declare X and Y to be of type VECTOR and FIXNUM respectively.
(loop for (x y) of-type (vector fixnum)
in l do ...)
\endcode
A \term{type specifier} for a destructuring pattern is a \term{tree} of
\term{type specifiers} with the same shape as the \term{tree} of
\term{variable} \term{names}, with the following exceptions:
\beginlist
\itemitem{\bull}
When aligning the \term{trees}, an \term{atom} in the
\term{tree} of \term{type specifiers} that matches a \term{cons}
in the variable tree declares the same \term{type} for each variable
in the subtree rooted at the \term{cons}.
\itemitem{\bull}
A \term{cons} in the \term{tree} of \term{type specifiers} that
matches an \term{atom} in the \term{tree} of \term{variable} \term{names}
is a \term{compound type specifer}.
\endlist
Destructuring allows \term{binding} of a set of variables to a corresponding
set of values anywhere that a value can normally be bound to a single
variable. During \macref{loop} expansion,
each variable in the variable list
is matched with the values in the values list. If there are more variables
in the variable list than there are values in the values list, the
remaining variables are given a value of \nil. If there are more
values than variables listed, the extra values are discarded.
To assign values from a list to the variables \f{a},
\f{b}, and \f{c}, the \loopref{for} clause could be used to
bind the variable \f{numlist} to the
\term{car} of the supplied \param{form},
and then another \loopref{for} clause could be used to bind the variables
\f{a}, \f{b}, and \f{c} \term{sequentially}.
\issue{LOOP-AND-DISCREPANCY:NO-REITERATION}
\code
;; Collect values by using FOR constructs.
(loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
for a of-type integer = (first numlist)
and b of-type integer = (second numlist)
and c of-type float = (third numlist)
collect (list c b a))
\EV ((4.0 2 1) (8.3 6 5) (10.4 9 8))
\endcode
\endissue{LOOP-AND-DISCREPANCY:NO-REITERATION}
Destructuring makes this process easier by allowing the variables to
be bound in each loop iteration.
\term{Types} can be declared by using a
list of \param{type-spec} arguments. If
all the \term{types}
are the same, a shorthand destructuring syntax can be used, as the second
example illustrates.
\code
;; Destructuring simplifies the process.
(loop for (a b c) of-type (integer integer float) in
'((1 2 4.0) (5 6 8.3) (8 9 10.4))
collect (list c b a))
\EV ((4.0 2 1) (8.3 6 5) (10.4 9 8))
;; If all the types are the same, this way is even simpler.
(loop for (a b c) of-type float in
'((1.0 2.0 4.0) (5.0 6.0 8.3) (8.0 9.0 10.4))
collect (list c b a))
\EV ((4.0 2.0 1.0) (8.3 6.0 5.0) (10.4 9.0 8.0))
\endcode
If destructuring is used to declare or initialize a number of groups
of variables into \term{types}, the \term{loop keyword} \loopref{and} can be used
to simplify the process further.
\issue{LOOP-AND-DISCREPANCY:NO-REITERATION}
\code
;; Initialize and declare variables in parallel by using the AND construct.\kern-7pt
(loop with (a b) of-type float = '(1.0 2.0)
and (c d) of-type integer = '(3 4)
and (e f)
return (list a b c d e f))
\EV (1.0 2.0 3 4 NIL NIL)
\endcode
\endissue{LOOP-AND-DISCREPANCY:NO-REITERATION}
If \nil\ is used in a destructuring list, no variable is provided for
its place.
\code
(loop for (a nil b) = '(1 2 3)
do (return (list a b)))
\EV (1 3)
\endcode
Note that
%% Replaced per Moon #42 (first public review) -kmp 6-May-93
%nonstandard lists
\term{dotted lists}
can specify destructuring.
\code
(loop for (x . y) = '(1 . 2)
do (return y))
\EV 2
(loop for ((a . b) (c . d)) of-type ((float . float) (integer . integer)) in
'(((1.2 . 2.4) (3 . 4)) ((3.4 . 4.6) (5 . 6)))
collect (list a b c d))
\EV ((1.2 2.4 3 4) (3.4 4.6 5 6))
\endcode
An error \oftype{program-error} is signaled (at macro expansion time)
if the same variable is bound twice in any variable-binding
clause of a single \macref{loop} expression. Such variables include
local variables, iteration control variables, and variables found by
destructuring.
\endsubsubsection%{Destructuring}
\beginsubsubsection{Restrictions on Side-Effects}
\issue{MAPPING-DESTRUCTIVE-INTERACTION:EXPLICITLY-VAGUE}
\Seesection\TraversalRules.
\endissue{MAPPING-DESTRUCTIVE-INTERACTION:EXPLICITLY-VAGUE}
\endsubsubsection%{Restrictions on Side-Effects}
\endsubsection%{Overview of the Loop Facility}
\beginsubsection{Variable Initialization and Stepping Clauses}
\DefineSection{LOOPVarInitAndStep}
\beginsubsubsection{Iteration Control}
Iteration control clauses allow direction of \macref{loop} iteration.
The \term{loop keywords} \loopref{for} and \loopref{as}
%, and \loopref{repeat}
designate iteration control clauses.
Iteration control clauses differ with respect to the specification of
termination tests and to the initialization and \term{stepping}\meaning{1}
of loop variables. Iteration clauses by themselves
do not cause the Loop Facility to return values, but they
can be used in conjunction with value-accumulation clauses to
return values.
All variables are initialized in the loop prologue.
A \term{variable} \term{binding} has \term{lexical scope}
unless it is proclaimed \declref{special};
thus, by default, the variable can be \term{accessed} only by \term{forms}
that lie textually within the \macref{loop}.
Stepping assignments are made in the loop body before any other \term{forms}
are evaluated in the body.
The variable argument in iteration control clauses can be a
destructuring list. A destructuring list
is a \term{tree} whose \term{non-nil} \term{atoms} are \term{variable} \term{names}.
\Seesection\DestructuringLOOPVars.
The iteration control clauses \loopref{for}, \loopref{as}, and \loopref{repeat}
must precede any other loop clauses, except
\loopref{initially}, \loopref{with}, and \loopref{named},
since they establish variable \term{bindings}.
When iteration control clauses are
used in a \macref{loop},
%Next line added for JonL:
the corresponding
termination tests in the loop body are evaluated
before any other loop body code is executed.
If multiple iteration clauses are used to control iteration, variable
initialization and \term{stepping}\meaning{1} occur \term{sequentially} by default.
The \loopref{and} construct can be used to connect two or more
iteration clauses when \term{sequential} \term{binding} and
\term{stepping}\meaning{1} are not necessary.
The iteration behavior of clauses joined by \loopref{and}
is analogous to the behavior of the macro \macref{do} with
respect to \macref{do*}.
The \loopref{for} and \loopref{as} clauses iterate by using one or more local
loop variables that are initialized to some value and that
can be modified or \term{stepped}\meaning{1} after each iteration.
For these clauses, iteration terminates when a local
variable reaches some supplied value or when some other loop clause
terminates iteration.
%!!! Barmar: These aren't the only ways for/as can step the variables.
At each iteration, variables can be
\term{stepped}\meaning{1} by an increment or a decrement
or can be assigned a new value by the evaluation of a \term{form}).
Destructuring can be used to assign
%% Removed per barmar--It is also used during stepping.
%initial
values to variables during iteration.
The \loopref{for} and \loopref{as} keywords are synonyms; they can be used
interchangeably. There are seven syntactic formats for these constructs.
In each syntactic format, the \term{type} of
\param{var} can be supplied by the optional \param{type-spec}
argument. If \param{var} is a destructuring list, the \term{type}
supplied by the \param{type-spec} argument must appropriately match
the elements of the list.
%!!! Barmar: "conventions" belong in the "Notes" section.
By convention, \loopref{for} introduces new iterations and \loopref{as}
introduces iterations that depend on a previous iteration specification.
\beginsubsubsubsection{The for-as-arithmetic subclause}
In the \i{for-as-arithmetic} subclause, the \loopref{for}
or \loopref{as} construct iterates from the value supplied by
\param{form1} to the value supplied by \param{form2} in increments or
decrements denoted by \param{form3}. Each
expression is evaluated only once and must evaluate to a \term{number}.
The variable \param{var} is bound to the value of
\param{form1} in the first iteration and is \term{stepped}\meaning{1}
by the value of \param{form3} in each succeeding iteration,
or by 1 if \param{form3} is not provided.
The following \term{loop keywords} serve as valid prepositions within this
syntax.
At least one of the
%three classes of
prepositions must be used;
and at most one from each line may be used in a single subclause.
\beginlist
\itemitem{\tt from | downfrom | upfrom}
\itemitem{\tt to | downto | upto | below | above}
\itemitem{\tt by}
\endlist
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
The prepositional phrases in each subclause may appear in any order.
For example, either ``\f{from x by y}'' or ``\f{by y from x}'' is permitted.
However, because left-to-right order of evaluation is preserved,
the effects will be different in the case of side effects.
\idxtext{order of evaluation}\idxtext{evaluation order}%
Consider:
\code
(let ((x 1)) (loop for i from x by (incf x) to 10 collect i))
\EV (1 3 5 7 9)
(let ((x 1)) (loop for i by (incf x) from x to 10 collect i))
\EV (2 4 6 8 10)
\endcode
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
The descriptions of the prepositions follow:
\beginlist
\itemitem{\tt from}
The \term{loop keyword} \loopref{from} specifies the value from which
\term{stepping}\meaning{1} begins, as supplied by \param{form1}.
\term{Stepping}\meaning{1} is incremental by default. If
decremental \term{stepping}\meaning{1} is desired,
the preposition \loopref{downto}
or \loopref{above} must be used with \param{form2}. For incremental
\term{stepping}\meaning{1}, the default \loopref{from} value is 0.
\itemitem{\tt downfrom, upfrom}
The \term{loop keyword} \loopref{downfrom}
indicates that the variable \param{var} is decreased in decrements
supplied by \param{form3}; the \term{loop keyword} \loopref{upfrom} indicates that
\param{var} is increased in increments supplied by \param{form3}.
\itemitem{\tt to}
The \term{loop keyword} \loopref{to} marks the end value
for \term{stepping}\meaning{1} supplied in \param{form2}.
\term{Stepping}\meaning{1} is incremental by default.
If decremental \term{stepping}\meaning{1} is desired,
the preposition \loopref{downfrom} must be used with \param{form1},
or else the preposition \loopref{downto} or \loopref{above} should be used instead
of \loopref{to} with \param{form2}.
\itemitem{\tt downto, upto}
The \term{loop keyword} \loopref{downto} specifies decremental \term{stepping};
the \term{loop keyword} \loopref{upto} specifies incremental \term{stepping}.
In both cases, the amount of change on each step is specified by \param{form3},
and the \macref{loop} terminates when the variable \param{var} passes
the value of \param{form2}.
Since there is no default for \param{form1} in decremental \term{stepping}\meaning{1},
a \param{form1} value must be supplied (using \loopref{from} or \loopref{downfrom})
when \loopref{downto} is supplied.
\itemitem{\tt below, above}
The \term{loop keywords} \loopref{below} and \loopref{above} are analogous to
\loopref{upto} and \loopref{downto} respectively. These keywords stop
iteration just before the value of the variable \param{var} reaches the value
supplied by \param{form2}; the end value of \param{form2} is not included.
Since there is no default for \param{form1} in decremental \term{stepping}\meaning{1},
a \param{form1} value must be supplied (using \loopref{from} or \loopref{downfrom})
when \loopref{above} is supplied.
\itemitem{\tt by}
The \term{loop keyword} \loopref{by} marks the increment or decrement supplied by
\param{form3}. The value of \param{form3} can be any
%!!! Jonl wants to know why "positive" here.
positive
\term{number}.
The default value is 1.
\endlist
In an iteration control clause, the \loopref{for} or \loopref{as} construct
causes termination when the supplied limit is reached. That is,
iteration continues until the value \param{var} is stepped to the
exclusive or inclusive limit supplied by \param{form2}. The range is
exclusive if \param{form3} increases or decreases \param{var}
to the value of \param{form2} without reaching that value; the loop
keywords \loopref{below} and \loopref{above} provide exclusive limits. An
inclusive limit allows \param{var} to attain the value of
\param{form2}; \loopref{to}, \loopref{downto}, and \loopref{upto} provide inclusive
limits.
%!!! JonL wonders if we maybe shouldn't define "incremental" and "decremental" here.
\beginsubsubsubsubsection{Examples of for-as-arithmetic subclause}
\code
;; Print some numbers.
(loop for i from 1 to 3
do (print i))
\OUT 1
\OUT 2
\OUT 3
\EV NIL
;; Print every third number.
(loop for i from 10 downto 1 by 3
do (print i))
\OUT 10
\OUT 7
\OUT 4
\OUT 1
\EV NIL
;; Step incrementally from the default starting value.
(loop for i below 3
do (print i))
\OUT 0
\OUT 1
\OUT 2
\EV NIL
\endcode
\endsubsubsubsubsection%{Examples of for-as-arithmetic subclause}
\endsubsubsubsection%{The for-as-arithmetic subclause}
\beginsubsubsubsection{The for-as-in-list subclause}
In the \i{for-as-in-list} subclause,
the \loopref{for}
or \loopref{as} construct iterates over the contents of a
\term{list}. It checks for
the end of the \term{list} as if by using \funref{endp}.
The variable \param{var} is bound to the successive elements of
the \term{list} in \param{form1} before each
iteration. At the end of each iteration, the function \param{step-fun}
is applied to the \term{list}; the default value for \param{step-fun} is
\funref{cdr}.
The \term{loop keywords} \loopref{in} and \loopref{by} serve as valid prepositions in
this syntax.
The \loopref{for} or \loopref{as} construct causes termination when the
end of the \term{list} is reached.
\beginsubsubsubsubsection{Examples of for-as-in-list subclause}
\issue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
%Added OF-TYPE in the third example. -kmp 29-Apr-93
\code
;; Print every item in a list.
(loop for item in '(1 2 3) do (print item))
\OUT 1
\OUT 2
\OUT 3
\EV NIL
;; Print every other item in a list.
(loop for item in '(1 2 3 4 5) by #'cddr
do (print item))
\OUT 1
\OUT 3
\OUT 5
\EV NIL
;; Destructure a list, and sum the x values using fixnum arithmetic.
(loop for (item . x) of-type (t . fixnum) in '((A . 1) (B . 2) (C . 3))
unless (eq item 'B) sum x)
\EV 4
\endcode
\endissue{LOOP-MISCELLANEOUS-REPAIRS:FIX}
\endsubsubsubsubsection%{Examples of for-as-in-list subclause}
\endsubsubsubsection%{The for-as-in-list subclause}
\beginsubsubsubsection{The for-as-on-list subclause}
\issue{LOOP-FOR-AS-ON-TYPO:FIX-TYPO}
In the \i{for-as-on-list} subclause, the \loopref{for} or \loopref{as}
construct iterates over
%the contents of
a \term{list}. It checks for the
end of the \term{list} as if by using \funref{atom}.
\endissue{LOOP-FOR-AS-ON-TYPO:FIX-TYPO}
The variable \param{var} is bound to the successive tails of the
\term{list} in
\param{form1}. At the end of each iteration, the function \param{step-fun}
is applied to the \term{list}; the default value for \param{step-fun} is \funref{cdr}.
The \term{loop keywords} \loopref{on} and \loopref{by} serve as valid
prepositions in this syntax.
The \loopref{for} or \loopref{as} construct causes termination when the
end of the \term{list} is reached.
\beginsubsubsubsubsection{Examples of for-as-on-list subclause}
\code
;; Collect successive tails of a list.
(loop for sublist on '(a b c d)
collect sublist)
\EV ((A B C D) (B C D) (C D) (D))
;; Print a list by using destructuring with the loop keyword ON.
(loop for (item) on '(1 2 3)
do (print item))
\OUT 1
\OUT 2
\OUT 3
\EV NIL
\endcode
\endsubsubsubsubsection%{Examples of for-as-on-list subclause}
\endsubsubsubsection%{The for-as-on-list subclause}
\beginsubsubsubsection{The for-as-equals-then subclause}
In the \i{for-as-equals-then} subclause
the \loopref{for}
or \loopref{as} construct
initializes the variable \param{var} by setting it to the
result of evaluating \param{form1} on the first iteration, then setting
it to the result of evaluating \param{form2} on the second and
subsequent iterations. If \param{form2} is omitted, the construct
uses \param{form1} on the second and
subsequent iterations.
%When \param{form2} is omitted, the expanded
% code shows the following optimization:
The \term{loop keywords} {$=$} and \loopref{then} serve as valid prepositions
in this syntax.
This construct does not provide any termination tests.
\beginsubsubsubsubsection{Examples of for-as-equals-then subclause}
%\code
%;; The original code:
% (prog (...)
% (setq x (some-value))
% tag (print x)
% (setq x (some-value))
% (go tag))
%
%;; The expanded code:
% (prog (...)
% tag (setq x (some-value))
% (print x)
% (go tag))
%\endcode
\code
;; Collect some numbers.
(loop for item = 1 then (+ item 10)
for iteration from 1 to 5
collect item)
\EV (1 11 21 31 41)
\endcode
\endsubsubsubsubsection%{Examples of for-as-equals-then subclause}
\endsubsubsubsection%{The for-as-equals-then subclause}
\beginsubsubsubsection{The for-as-across subclause}
In the \i{for-as-across} subclause the \loopref{for}
or \loopref{as} construct binds the variable \param{var} to the value of
each element in the array \param{vector}.
The \term{loop keyword} \loopref{across} marks the array \param{vector}; \loopref{across}
is used as a preposition in this syntax.
Iteration stops when there are no more elements in the supplied
\term{array} that can be referenced.
Some implementations might recognize a \specref{the} special form
in the \param{vector} form to produce more efficient code.
\beginsubsubsubsubsection{Examples of for-as-across subclause}
\code
(loop for char across (the simple-string (find-message channel))
do (write-char char stream))
\endcode
\endsubsubsubsubsection%{Examples of for-as-across subclause}
\endsubsubsubsection%{The for-as-across subclause}
\beginsubsubsubsection{The for-as-hash subclause}
In the \i{for-as-hash} subclause
the \loopref{for}
or \loopref{as} construct
iterates over the elements, keys, and values of a \term{hash-table}.
In this syntax, a compound preposition is used to designate access to a
\term{hash table}.
The variable \param{var} takes on the value of each hash key
or hash value in the supplied \param{hash-table}.
The following \term{loop keywords} serve as valid prepositions within this syntax: